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.c83
1 files changed, 27 insertions, 56 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c
index d37d0fd..368594d 100644
--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -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,7 +609,7 @@ 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
@@ -781,7 +768,7 @@ change_section (const char *name,
|| startswith (name, ".note.gnu"))
flags |= SEC_ELF_OCTETS;
}
-
+
if (old_sec == NULL)
{
symbolS *secsym;
@@ -1151,7 +1138,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);
}
@@ -2273,39 +2260,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 +2377,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;
}
@@ -2805,7 +2777,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 +3307,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
};