X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=bfd%2Felf-properties.c;h=95e66ffdff450f1c013c3d4ad9e2aa995403ca13;hb=74b4ba13b642fc0afd1c6cc7c67c9ae1f2297244;hp=a0456f8df9fadf5c5bf8dc66bc237f372732f808;hpb=61fbc1aa06ace2eedead83c4526b06941a1d33bb;p=external%2Fbinutils.git diff --git a/bfd/elf-properties.c b/bfd/elf-properties.c index a0456f8..95e66ff 100644 --- a/bfd/elf-properties.c +++ b/bfd/elf-properties.c @@ -69,6 +69,7 @@ _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz) memset (p, 0, sizeof (*p)); p->property.pr_type = type; p->property.pr_datasz = datasz; + p->property.filename = abfd->filename; p->next = *lastp; *lastp = p; return &p->property; @@ -163,6 +164,26 @@ bad_size: prop->pr_kind = property_number; goto next; + case GNU_PROPERTY_COMPILER_FLAGS: + /* Note that annobin uses 4-byte alignment even on 64-bit targets. */ + if (!((datasz == 4) || (datasz == 8))) + { + _bfd_error_handler + (_("warning: %B: corrupt compiler flags: 0x%x\n"), + abfd, datasz); + /* Clear all properties. */ + elf_properties (abfd) = NULL; + return FALSE; + } + prop = _bfd_elf_get_property (abfd, type, datasz); + if (datasz == 8) + prop->u.number = bfd_h_get_64 (abfd, ptr); + else + prop->u.number = bfd_h_get_32 (abfd, ptr); + + prop->pr_kind = property_number; + goto next; + default: break; } @@ -184,6 +205,110 @@ next: return TRUE; } +/* If validation bits are set - compare bit flags for equality. */ +inline static bfd_boolean +elf_gnu_property_validate_flag (bfd_vma anum, + bfd_vma bnum, + bfd_vma validation_bit_flag, + bfd_vma validation_bit) +{ + if ((anum & validation_bit_flag) && (bnum & validation_bit_flag) + && ((anum & validation_bit) != (bnum & validation_bit))) + { + return FALSE; + } + return TRUE; +} + +static bfd_boolean +elf_validate_compiler_flags_properties (elf_property *aprop, + elf_property *bprop) +{ + bfd_boolean is_flag_set; + + /* Sanity check to verify correct usage. */ + BFD_ASSERT(aprop); + BFD_ASSERT(bprop); + + if (aprop->pr_type != bprop->pr_type) + return TRUE; + + BFD_ASSERT(aprop->pr_type == GNU_PROPERTY_COMPILER_FLAGS); + + /* Return TRUE if compiler flags are identical (likely?). */ + if (aprop->u.number == bprop->u.number) + return TRUE; + + if (!elf_gnu_property_validate_flag(aprop->u.number, + bprop->u.number, + GNU_PROPERTY_SANITIZE_VALIDATION, + GNU_PROPERTY_SANITIZE_ADDRESS)) + { + is_flag_set = bprop->u.number & GNU_PROPERTY_SANITIZE_ADDRESS; + _bfd_error_handler + (_("%s: ERROR: Validation failed, linking %s object with previous %s"), + bprop->filename, is_flag_set ? "sanitized" : "unsanitized", + !is_flag_set ? "sanitized" : "unsanitized"); + return FALSE; + } + + if (!elf_gnu_property_validate_flag(aprop->u.number, + bprop->u.number, + GNU_PROPERTY_USECXX_VALIDATION, + GNU_PROPERTY_USECXX11_ABI)) + { + is_flag_set = bprop->u.number & GNU_PROPERTY_USECXX11_ABI; + _bfd_error_handler + (_("ERROR: Validation failed, linking %s ABI object with %s ABI"), + bprop->filename, is_flag_set ? "pre-cxx11" : "cxx11", + !is_flag_set ? "pre-cxx11" : "cxx11"); + return FALSE; + } + + return TRUE; +} + + +/* Merge bprop into aprop according compiler-flags properties, return TRUE if */ +/* aprop is updated. */ +static bfd_boolean +elf_merge_gnu_properties_compiler_flags (elf_property *aprop, + elf_property *bprop) +{ + bfd_boolean is_updated = FALSE; + /* Likely that objects have the same properties. */ + if (aprop->u.number == bprop->u.number) { + return FALSE; + } + + /* Validation bit + no-validation bit = validation bit. */ + if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_VALIDATION) + { + aprop->u.number |= GNU_PROPERTY_SANITIZE_VALIDATION; + is_updated = TRUE; + } + /* Sanitized object + unsanitized results = sanitized final object. */ + if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_SANITIZE_ADDRESS) + { + aprop->u.number |= GNU_PROPERTY_SANITIZE_ADDRESS; + is_updated = TRUE; + } + + if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX_VALIDATION) + { + aprop->u.number |= GNU_PROPERTY_USECXX_VALIDATION; + is_updated = TRUE; + } + + if ((aprop->u.number ^ bprop->u.number) & GNU_PROPERTY_USECXX11_ABI) + { + aprop->u.number |= GNU_PROPERTY_USECXX11_ABI; + is_updated = TRUE; + } + + return is_updated; +} + /* Merge GNU property BPROP with APROP. If APROP isn't NULL, return TRUE if APROP is updated. Otherwise, return TRUE if BPROP should be merged with ABFD. */ @@ -218,6 +343,44 @@ elf_merge_gnu_properties (bfd *abfd, elf_property *aprop, /* Return TRUE if APROP is NULL to indicate that BPROP should be added to ABFD. */ return aprop == NULL; + /* FALLTHROUGH */ + + case GNU_PROPERTY_COMPILER_FLAGS: + { + bfd_boolean is_updated; + if (aprop != NULL && bprop != NULL) + { +#ifdef ENABLE_ANNOBIN_VERIFICATION + if (!elf_validate_compiler_flags_properties (aprop, bprop)) + { + _bfd_error_handler(_("ERROR: Linking failed due to incompatible " + "compilation flags used to generate objects\n")); + /* Strict mode, abort. */ +#ifdef ENABLE_ANNOBIN_VERIFICATION_STRICT + _exit (EXIT_FAILURE); +#endif + } +#endif + is_updated = elf_merge_gnu_properties_compiler_flags (aprop, bprop); + } + else + { + is_updated = FALSE; + /* aprop or bprop is NULL, warn for missing GNU_PROPERTY_COMPILER_FLAGS. + + This is too noisy since glibc's crt{i,n}.o are compiled with + predefined flags (without annobin support), so we'll have at + least 2x of the following warning for every linking. May be + enabled after we verified crt* compilation with plugins. */ + /* if (bprop == NULL) + _bfd_error_handler + (_("WARNING: not found (generated by annobin gcc plugin), " + "runtime verification may be incomplete"), + NOTE_GNU_PROPERTY_SECTION_NAME); */ + } + return is_updated; + } + /* FALLTHROUGH */ default: /* Never should happen. */ @@ -380,6 +543,9 @@ _bfd_elf_link_setup_gnu_properties (struct bfd_link_info *info) sec = bfd_get_section_by_name (first_pbfd, NOTE_GNU_PROPERTY_SECTION_NAME); + if (!sec) + return; + /* Update stack size in .note.gnu.property with -z stack-size=N if N > 0. */ if (info->stacksize > 0)