aboutsummaryrefslogtreecommitdiff
path: root/gas/config/obj-elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gas/config/obj-elf.c')
-rw-r--r--gas/config/obj-elf.c246
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 (&notes, s, name_length + 1);
- S_SET_NAME (sym, (const char *) obstack_finish (&notes));
+ S_SET_NAME (sym, obstack_finish (&notes));
}
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
};