diff options
Diffstat (limited to 'gas/config/obj-elf.c')
-rw-r--r-- | gas/config/obj-elf.c | 246 |
1 files changed, 123 insertions, 123 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index d37d0fd..ccf020f 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -205,7 +205,7 @@ elf_file_symbol (const char *s) if (name_length > strlen (S_GET_NAME (sym))) { obstack_grow (¬es, s, name_length + 1); - S_SET_NAME (sym, (const char *) obstack_finish (¬es)); + S_SET_NAME (sym, obstack_finish (¬es)); } else strcpy ((char *) S_GET_NAME (sym), s); @@ -481,7 +481,7 @@ match_section (const asection *sec, const struct elf_section_match *match) static bool get_section_by_match (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf) { - struct elf_section_match *match = (struct elf_section_match *) inf; + struct elf_section_match *match = inf; const char *gname = match->group_name; const char *group_name = elf_group_name (sec); @@ -492,13 +492,6 @@ get_section_by_match (bfd *abfd ATTRIBUTE_UNUSED, asection *sec, void *inf) && match_section (sec, match)); } -static void -free_section_idx (void *ent) -{ - string_tuple_t *tuple = ent; - free ((char *) tuple->value); -} - /* Go look in section lists kept per group for SEC_NAME with properties given by MATCH. If info for the group named by MATCH->GROUP_NAME has been initialised, set GROUP_IDX. */ @@ -506,24 +499,24 @@ free_section_idx (void *ent) static asection * group_section_find (const struct elf_section_match *match, const char *sec_name, - unsigned int **group_idx) + unsigned int *group_idx) { if (!groups.indexes) { groups.num_group = 0; groups.head = NULL; groups.indexes = htab_create_alloc (16, hash_string_tuple, eq_string_tuple, - free_section_idx, notes_calloc, NULL); - *group_idx = NULL; + NULL, notes_calloc, NULL); + *group_idx = ~0u; return NULL; } - *group_idx = str_hash_find (groups.indexes, match->group_name); - if (*group_idx == NULL) + *group_idx = str_hash_find_int (groups.indexes, match->group_name); + if (*group_idx == ~0u) return NULL; asection *s; - for (s = groups.head[**group_idx]; s != NULL; s = elf_next_in_group (s)) + for (s = groups.head[*group_idx]; s != NULL; s = elf_next_in_group (s)) if ((s->name == sec_name || strcmp (s->name, sec_name) == 0) && match_section (s, match)) @@ -537,12 +530,12 @@ group_section_find (const struct elf_section_match *match, static void group_section_insert (const struct elf_section_match *match, asection *sec, - unsigned int **group_idx) + unsigned int *group_idx) { - if (*group_idx != NULL) + if (*group_idx != ~0u) { - elf_next_in_group (sec) = groups.head[**group_idx]; - groups.head[**group_idx] = sec; + elf_next_in_group (sec) = groups.head[*group_idx]; + groups.head[*group_idx] = sec; return; } @@ -553,14 +546,8 @@ group_section_insert (const struct elf_section_match *match, groups.num_group += 1; /* We keep the index into groups.head rather than the entry address - because groups.head may be realloc'd, and because str_hash values - are a void* we make a copy of the index. Strictly speaking there - is no guarantee that void* can represent any int value, so doing - without the indirection by casting an int or even uintptr_t may - for example lose lsbs of the value. */ - unsigned int *idx_ptr = XNEW (unsigned int); - *idx_ptr = i; - str_hash_insert (groups.indexes, match->group_name, idx_ptr, 0); + because groups.head may be realloc'd. */ + str_hash_insert_int (groups.indexes, match->group_name, i, 0); } /* Handle the .section pseudo-op. This code supports two different @@ -622,12 +609,12 @@ change_section (const char *name, obj_elf_section_change_hook (); - unsigned int *group_idx = NULL; + unsigned int group_idx = ~0u; if (match_p->group_name) old_sec = group_section_find (match_p, name, &group_idx); else old_sec = bfd_get_section_by_name_if (stdoutput, name, get_section_by_match, - (void *) match_p); + match_p); if (old_sec) { sec = old_sec; @@ -781,7 +768,7 @@ change_section (const char *name, || startswith (name, ".note.gnu")) flags |= SEC_ELF_OCTETS; } - + if (old_sec == NULL) { symbolS *secsym; @@ -805,7 +792,7 @@ change_section (const char *name, = match_p->linked_to_symbol_name; bfd_set_section_flags (sec, flags); - if (flags & (SEC_MERGE | SEC_STRINGS)) + if (entsize != 0) sec->entsize = entsize; elf_group_name (sec) = match_p->group_name; @@ -860,7 +847,7 @@ change_section (const char *name, processor or application specific attribute as suspicious? */ elf_section_flags (sec) = attr; - if ((flags & (SEC_MERGE | SEC_STRINGS)) + if (entsize != 0 && old_sec->entsize != (unsigned) entsize) as_bad (_("changed section entity size for %s"), name); } @@ -883,8 +870,9 @@ obj_elf_change_section (const char *name, } static bfd_vma -obj_elf_parse_section_letters (char *str, size_t len, - bool *is_clone, int *inherit, bfd_vma *gnu_attr) +obj_elf_parse_section_letters (char *str, size_t len, bool push, + bool *is_clone, int *inherit, bfd_vma *gnu_attr, + bool *has_entsize) { bfd_vma attr = 0; @@ -909,6 +897,11 @@ obj_elf_parse_section_letters (char *str, size_t len, } } break; + case 'd': + if (gnu_attr == NULL) + goto unrecognized; + *gnu_attr |= SHF_GNU_MBIND; + break; case 'e': attr |= SHF_EXCLUDE; break; @@ -921,33 +914,36 @@ obj_elf_parse_section_letters (char *str, size_t len, case 'x': attr |= SHF_EXECINSTR; break; + case 'E': + *has_entsize = true; + break; + case 'G': + attr |= SHF_GROUP; + break; case 'M': attr |= SHF_MERGE; break; + case 'R': + if (gnu_attr == NULL) + goto unrecognized; + *gnu_attr |= SHF_GNU_RETAIN; + break; case 'S': attr |= SHF_STRINGS; break; - case 'G': - attr |= SHF_GROUP; - break; case 'T': attr |= SHF_TLS; break; - case 'd': - *gnu_attr |= SHF_GNU_MBIND; - break; - case 'R': - *gnu_attr |= SHF_GNU_RETAIN; - break; case '?': *is_clone = true; break; default: + unrecognized: { - const char *bad_msg = _("unrecognized .section attribute:" - " want a,e,o,w,x,M,S,G,T or number"); + const char *md_extra = ""; + #ifdef md_elf_section_letter - bfd_vma md_attr = md_elf_section_letter (*str, &bad_msg); + bfd_vma md_attr = md_elf_section_letter (*str, &md_extra); if (md_attr != (bfd_vma) -1) attr |= md_attr; else @@ -955,23 +951,14 @@ obj_elf_parse_section_letters (char *str, size_t len, if (ISDIGIT (*str)) { char * end; - struct elf_backend_data *bed; bfd_vma numeric_flags = strtoul (str, &end, 0); attr |= numeric_flags; - bed = (struct elf_backend_data *) - get_elf_backend_data (stdoutput); - - if (bed->elf_osabi == ELFOSABI_NONE - || bed->elf_osabi == ELFOSABI_STANDALONE - || bed->elf_osabi == ELFOSABI_GNU - || bed->elf_osabi == ELFOSABI_FREEBSD) + if (gnu_attr != NULL) { /* Add flags in the SHF_MASKOS range to gnu_attr for OSABIs that support those flags. - Also adding the flags for ELFOSABI_{NONE,STANDALONE} - allows them to be validated later in obj_elf_section. We can't just always set these bits in gnu_attr for all OSABIs, since Binutils does not recognize all SHF_MASKOS bits for non-GNU OSABIs. It's therefore @@ -987,10 +974,19 @@ obj_elf_parse_section_letters (char *str, size_t len, len -= (end - str); str = end; } - else if (!attr && !*gnu_attr && (*str == '+' || *str == '-')) + else if (!*inherit && !attr + && (gnu_attr == NULL || !*gnu_attr) + && (*str == '+' || *str == '-')) *inherit = *str == '+' ? 1 : -1; else - as_fatal ("%s", bad_msg); + { + as_bad (_("unrecognized .%ssection attribute: want %s%s%s,? or number"), + push ? "push" : "", + gnu_attr != NULL ? "a,d,e,o,w,x,E,G,M,R,S,T" + : "a,e,o,w,x,E,G,M,S,T", + md_extra != NULL ? "," : "", md_extra); + return attr; + } } break; } @@ -1151,7 +1147,7 @@ elf_set_group_name (asection *sec, const char *gname) & SEC_ASSEMBLER_SHF_MASK); match.flags = bfd_section_flags (sec) & SEC_ASSEMBLER_SECTION_ID; - unsigned int *group_idx; + unsigned int group_idx; if (!group_section_find (&match, sec->name, &group_idx)) group_section_insert (&match, sec, &group_idx); } @@ -1177,6 +1173,15 @@ obj_elf_attach_to_group (int dummy ATTRIBUTE_UNUSED) elf_set_group_name (now_seg, gname); } +/* Handle section related directives. + + Note on support for SFrame sections: These are generally expected to be + generated by the assembler. However, this function permits their direct + creation by the user. At the moment though, we go no extra mile by adding + an explicit @sframe for SHT_GNU_SFRAME (using the numeric value of section + type should suffice); Nor do we implement any outright refusal for + non-supported targets via ELFOSABI-specific checks. */ + void obj_elf_section (int push) { @@ -1186,7 +1191,7 @@ obj_elf_section (int push) bfd_vma attr; bfd_vma gnu_attr; int entsize; - bool linkonce; + bool linkonce, has_entsize; subsegT new_subsection = 0; struct elf_section_match match; unsigned long linked_to_section_index = -1UL; @@ -1231,6 +1236,7 @@ obj_elf_section (int push) attr = 0; gnu_attr = 0; entsize = 0; + has_entsize = false; linkonce = 0; if (*input_line_pointer == ',') @@ -1242,7 +1248,7 @@ obj_elf_section (int push) if (push && ISDIGIT (*input_line_pointer)) { /* .pushsection has an optional subsection. */ - new_subsection = (subsegT) get_absolute_expression (); + new_subsection = get_absolute_expression (); SKIP_WHITESPACE (); @@ -1266,8 +1272,17 @@ obj_elf_section (int push) ignore_rest_of_line (); return; } - attr = obj_elf_parse_section_letters (beg, strlen (beg), &is_clone, - &inherit, &gnu_attr); + + const struct elf_backend_data *bed = get_elf_backend_data (stdoutput); + attr = obj_elf_parse_section_letters (beg, strlen (beg), push, + &is_clone, &inherit, + bed->elf_osabi == ELFOSABI_NONE + || (bed->elf_osabi + == ELFOSABI_GNU) + || (bed->elf_osabi + == ELFOSABI_FREEBSD) + ? &gnu_attr : NULL, + &has_entsize); if (inherit > 0) attr |= elf_section_flags (now_seg); @@ -1276,6 +1291,9 @@ obj_elf_section (int push) if (inherit) type = elf_section_type (now_seg); + if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0) + has_entsize = true; + SKIP_WHITESPACE (); if (*input_line_pointer == ',') { @@ -1315,16 +1333,18 @@ obj_elf_section (int push) } SKIP_WHITESPACE (); - if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 - && *input_line_pointer == ',') + if (has_entsize && *input_line_pointer == ',') { ++input_line_pointer; SKIP_WHITESPACE (); if (inherit && *input_line_pointer == ',' + && ((bfd_section_flags (now_seg) + & (SEC_MERGE | SEC_STRINGS)) != 0 + || now_seg->entsize)) + goto fetch_entsize; + if (is_end_of_stmt (*input_line_pointer) && (bfd_section_flags (now_seg) & (SEC_MERGE | SEC_STRINGS)) != 0) - goto fetch_entsize; - if (is_end_of_stmt (*input_line_pointer)) { /* ??? This is here for older versions of gcc that test for gas string merge support with @@ -1332,7 +1352,7 @@ obj_elf_section (int push) Unfortunately '@' begins a comment on arm. This isn't as_warn because gcc tests with --fatal-warnings. */ - as_tsktsk (_("missing merge / string entity size, 1 assumed")); + as_tsktsk (_("missing section entity size, 1 assumed")); entsize = 1; } else @@ -1341,15 +1361,17 @@ obj_elf_section (int push) SKIP_WHITESPACE (); if (entsize <= 0) { - as_warn (_("invalid merge / string entity size")); + as_warn (_("invalid section entity size")); attr &= ~(SHF_MERGE | SHF_STRINGS); + has_entsize = false; entsize = 0; } } } - else if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && inherit - && (bfd_section_flags (now_seg) - & (SEC_MERGE | SEC_STRINGS)) != 0) + else if (has_entsize && inherit + && ((bfd_section_flags (now_seg) + & (SEC_MERGE | SEC_STRINGS)) != 0 + || now_seg->entsize)) { fetch_entsize: entsize = now_seg->entsize; @@ -1360,6 +1382,7 @@ obj_elf_section (int push) entsize must be specified if SHF_MERGE is set. */ as_warn (_("entity size for SHF_MERGE not specified")); attr &= ~(SHF_MERGE | SHF_STRINGS); + has_entsize = false; } else if ((attr & SHF_STRINGS) != 0) { @@ -1369,6 +1392,11 @@ obj_elf_section (int push) compatibility. */ entsize = 1; } + else if (has_entsize) + { + as_warn (_("entity size not specified")); + has_entsize = false; + } if ((attr & (SHF_MERGE | SHF_STRINGS)) != 0 && type == SHT_NOBITS) as_warn (_("bogus SHF_MERGE / SHF_STRINGS for SHT_NOBITS section")); @@ -1473,7 +1501,7 @@ obj_elf_section (int push) char *t = input_line_pointer; match.sh_info = strtoul (input_line_pointer, &input_line_pointer, 0); - if (match.sh_info == (unsigned int) -1) + if (match.sh_info == -1u) { as_warn (_("unsupported mbind section info: %s"), t); match.sh_info = 0; @@ -1510,8 +1538,7 @@ obj_elf_section (int push) errno = 0; id = strtoul (input_line_pointer, &input_line_pointer, 0); - overflow = (id == (unsigned long) -1 - && errno == ERANGE); + overflow = id == -1ul && errno == ERANGE; } else { @@ -1520,7 +1547,7 @@ obj_elf_section (int push) (const char **) &input_line_pointer, 0); overflow = id == ~(bfd_vma) 0; } - if (overflow || id > (unsigned int) -1) + if (overflow || id > -1u) { char *linefeed, saved_char = 0; if ((linefeed = strchr (t, '\n')) != NULL) @@ -1578,28 +1605,17 @@ obj_elf_section (int push) if ((gnu_attr & (SHF_GNU_MBIND | SHF_GNU_RETAIN)) != 0) { - const struct elf_backend_data *bed; bool mbind_p = (gnu_attr & SHF_GNU_MBIND) != 0; if (mbind_p && (attr & SHF_ALLOC) == 0) as_bad (_("SHF_ALLOC isn't set for GNU_MBIND section: %s"), name); - bed = get_elf_backend_data (stdoutput); - - if (bed->elf_osabi != ELFOSABI_GNU - && bed->elf_osabi != ELFOSABI_FREEBSD - && bed->elf_osabi != ELFOSABI_NONE) - as_bad (_("%s section is supported only by GNU and FreeBSD targets"), - mbind_p ? "GNU_MBIND" : "GNU_RETAIN"); - else - { - if (mbind_p) - elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind; - if ((gnu_attr & SHF_GNU_RETAIN) != 0) - elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_retain; + if (mbind_p) + elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind; + if ((gnu_attr & SHF_GNU_RETAIN) != 0) + elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_retain; - attr |= gnu_attr; - } + attr |= gnu_attr; } change_section (name, type, attr, entsize, &match, linkonce, push, @@ -1627,7 +1643,7 @@ obj_elf_bss (int i ATTRIBUTE_UNUSED) obj_elf_section_change_hook (); temp = get_absolute_expression (); - subseg_set (bss_section, (subsegT) temp); + subseg_set (bss_section, temp); demand_empty_rest_of_line (); #ifdef md_elf_section_change_hook @@ -1701,7 +1717,7 @@ obj_elf_subsection (int ignore ATTRIBUTE_UNUSED) obj_elf_section_change_hook (); temp = get_absolute_expression (); - subseg_set (now_seg, (subsegT) temp); + subseg_set (now_seg, temp); demand_empty_rest_of_line (); #ifdef md_elf_section_change_hook @@ -2273,39 +2289,25 @@ elf_obj_symbol_new_hook (symbolS *symbolP) #endif } -/* Deduplicate size expressions. We might get into trouble with - multiple freeing or use after free if we leave them pointing to the - same expressionS. */ - +/* If size is unset, copy size from src. Because we don't track whether + .size has been used, we can't differentiate .size dest, 0 from the case + where dest's size is unset. */ void -elf_obj_symbol_clone_hook (symbolS *newsym, symbolS *orgsym ATTRIBUTE_UNUSED) +elf_copy_symbol_size (symbolS *dest, symbolS *src) { - struct elf_obj_sy *newelf = symbol_get_obj (newsym); - if (newelf->size) + struct elf_obj_sy *srcelf = symbol_get_obj (src); + struct elf_obj_sy *destelf = symbol_get_obj (dest); + if (!destelf->size && S_GET_SIZE (dest) == 0) { - expressionS *exp = XNEW (expressionS); - *exp = *newelf->size; - newelf->size = exp; + destelf->size = srcelf->size; + S_SET_SIZE (dest, S_GET_SIZE (src)); } } void elf_copy_symbol_attributes (symbolS *dest, symbolS *src) { - struct elf_obj_sy *srcelf = symbol_get_obj (src); - struct elf_obj_sy *destelf = symbol_get_obj (dest); - /* If size is unset, copy size from src. Because we don't track whether - .size has been used, we can't differentiate .size dest, 0 from the case - where dest's size is unset. */ - if (!destelf->size && S_GET_SIZE (dest) == 0) - { - if (srcelf->size) - { - destelf->size = XNEW (expressionS); - *destelf->size = *srcelf->size; - } - S_SET_SIZE (dest, S_GET_SIZE (src)); - } + elf_copy_symbol_size (dest, src); /* Don't copy visibility. */ S_SET_OTHER (dest, (ELF_ST_VISIBILITY (S_GET_OTHER (dest)) | (S_GET_OTHER (src) & ~ELF_ST_VISIBILITY (-1)))); @@ -2404,12 +2406,11 @@ obj_elf_size (int ignore ATTRIBUTE_UNUSED) if (exp.X_op == O_constant) { S_SET_SIZE (sym, exp.X_add_number); - xfree (symbol_get_obj (sym)->size); symbol_get_obj (sym)->size = NULL; } else { - symbol_get_obj (sym)->size = XNEW (expressionS); + symbol_get_obj (sym)->size = notes_alloc (sizeof (exp)); *symbol_get_obj (sym)->size = exp; } @@ -2719,7 +2720,7 @@ set_additional_section_info (bfd *abfd, if (!strcmp ("str", sec->name + strlen (sec->name) - 3)) return; - name = concat (sec->name, "str", NULL); + name = concat (sec->name, "str", (const char *) NULL); strsec = bfd_get_section_by_name (abfd, name); if (strsec) strsz = bfd_section_size (strsec); @@ -2805,7 +2806,6 @@ elf_frob_symbol (symbolS *symp, int *puntp) as_warn (_(".size expression for %s " "does not evaluate to a constant"), S_GET_NAME (symp)); } - free (sy_obj->size); sy_obj->size = NULL; } @@ -3336,7 +3336,7 @@ const struct format_ops elf_format_ops = #endif elf_obj_read_begin_hook, elf_obj_symbol_new_hook, - elf_obj_symbol_clone_hook, + 0, elf_adjust_symtab }; |