summaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorAlan Modra <amodra@bigpond.net.au>2007-09-26 12:29:41 +0000
committerAlan Modra <amodra@bigpond.net.au>2007-09-26 12:29:41 +0000
commit980249196b7b34bc780cc762c4af5e999c0f9702 (patch)
tree1054420e9fba74e8f0978094775c9748d154700c /bfd
parentba315106d7763a23982342b4b869f1e0e5839bfa (diff)
downloadbinutils-redhat-980249196b7b34bc780cc762c4af5e999c0f9702.tar.gz
* elflink.c (set_symbol_value): Add isymbuf and locsymcount
params. Change symidx to a size_t. Don't access past end of symbol buffer. (resolve_symbol): Add isymbuf param and use instead of finfo->internal_syms. (eval_symbol, evaluate_complex_relocation_symbols): Likewise. (elf_link_input_bfd): Don't read symbols specially for evaluate_complex_relocation_symbols.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog11
-rw-r--r--bfd/elflink.c116
2 files changed, 70 insertions, 57 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index f93f75669e..afbd748ebc 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,14 @@
+2007-09-26 Alan Modra <amodra@bigpond.net.au>
+
+ * elflink.c (set_symbol_value): Add isymbuf and locsymcount
+ params. Change symidx to a size_t. Don't access past end
+ of symbol buffer.
+ (resolve_symbol): Add isymbuf param and use instead of
+ finfo->internal_syms.
+ (eval_symbol, evaluate_complex_relocation_symbols): Likewise.
+ (elf_link_input_bfd): Don't read symbols specially for
+ evaluate_complex_relocation_symbols.
+
2007-09-26 Tristan Gingold <gingold@adacore.com>
* som.c (som_get_reloc_upper_bound): If there are no relocs return
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 8e17f89790..ce59c3abf1 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -7230,38 +7230,43 @@ struct elf_outext_info
static void
set_symbol_value (bfd * bfd_with_globals,
- struct elf_final_link_info * finfo,
- int symidx,
+ Elf_Internal_Sym * isymbuf,
+ size_t locsymcount,
+ size_t symidx,
bfd_vma val)
{
- bfd_boolean is_local;
- Elf_Internal_Sym * sym;
- struct elf_link_hash_entry ** sym_hashes;
- struct elf_link_hash_entry * h;
+ struct elf_link_hash_entry **sym_hashes;
+ struct elf_link_hash_entry *h;
+ size_t extsymoff = locsymcount;
- sym_hashes = elf_sym_hashes (bfd_with_globals);
- sym = finfo->internal_syms + symidx;
- is_local = ELF_ST_BIND(sym->st_info) == STB_LOCAL;
-
- if (is_local)
- {
- /* It is a local symbol: move it to the
- "absolute" section and give it a value. */
- sym->st_shndx = SHN_ABS;
- sym->st_value = val;
- }
- else
+ if (symidx < locsymcount)
{
- /* It is a global symbol: set its link type
- to "defined" and give it a value. */
- h = sym_hashes [symidx];
- while (h->root.type == bfd_link_hash_indirect
- || h->root.type == bfd_link_hash_warning)
- h = (struct elf_link_hash_entry *) h->root.u.i.link;
- h->root.type = bfd_link_hash_defined;
- h->root.u.def.value = val;
- h->root.u.def.section = bfd_abs_section_ptr;
+ Elf_Internal_Sym *sym;
+
+ sym = isymbuf + symidx;
+ if (ELF_ST_BIND (sym->st_info) == STB_LOCAL)
+ {
+ /* It is a local symbol: move it to the
+ "absolute" section and give it a value. */
+ sym->st_shndx = SHN_ABS;
+ sym->st_value = val;
+ return;
+ }
+ BFD_ASSERT (elf_bad_symtab (bfd_with_globals));
+ extsymoff = 0;
}
+
+ /* It is a global symbol: set its link type
+ to "defined" and give it a value. */
+
+ sym_hashes = elf_sym_hashes (bfd_with_globals);
+ h = sym_hashes [symidx - extsymoff];
+ while (h->root.type == bfd_link_hash_indirect
+ || h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ h->root.type = bfd_link_hash_defined;
+ h->root.u.def.value = val;
+ h->root.u.def.section = bfd_abs_section_ptr;
}
static bfd_boolean
@@ -7269,6 +7274,7 @@ resolve_symbol (const char * name,
bfd * input_bfd,
struct elf_final_link_info * finfo,
bfd_vma * result,
+ Elf_Internal_Sym * isymbuf,
size_t locsymcount)
{
Elf_Internal_Sym * sym;
@@ -7282,7 +7288,7 @@ resolve_symbol (const char * name,
for (i = 0; i < locsymcount; ++ i)
{
- sym = finfo->internal_syms + i;
+ sym = isymbuf + i;
sec = finfo->sections [i];
if (ELF_ST_BIND (sym->st_info) != STB_LOCAL)
@@ -7402,6 +7408,7 @@ eval_symbol (bfd_vma * result,
struct elf_final_link_info * finfo,
bfd_vma addr,
bfd_vma section_offset,
+ Elf_Internal_Sym * isymbuf,
size_t locsymcount,
int signed_p)
{
@@ -7459,8 +7466,9 @@ eval_symbol (bfd_vma * result,
if (symbol_is_section)
{
- if ((resolve_section (symbuf, finfo->output_bfd->sections, result) != TRUE)
- && (resolve_symbol (symbuf, input_bfd, finfo, result, locsymcount) != TRUE))
+ if (!resolve_section (symbuf, finfo->output_bfd->sections, result)
+ && !resolve_symbol (symbuf, input_bfd, finfo, result,
+ isymbuf, locsymcount))
{
undefined_reference ("section", symbuf);
return FALSE;
@@ -7468,9 +7476,10 @@ eval_symbol (bfd_vma * result,
}
else
{
- if ((resolve_symbol (symbuf, input_bfd, finfo, result, locsymcount) != TRUE)
- && (resolve_section (symbuf, finfo->output_bfd->sections,
- result) != TRUE))
+ if (!resolve_symbol (symbuf, input_bfd, finfo, result,
+ isymbuf, locsymcount)
+ && !resolve_section (symbuf, finfo->output_bfd->sections,
+ result))
{
undefined_reference ("symbol", symbuf);
return FALSE;
@@ -7487,9 +7496,9 @@ eval_symbol (bfd_vma * result,
sym += strlen (#op); \
if (* sym == ':') \
++ sym; \
- if (eval_symbol (& a, sym, & sym, input_bfd, finfo, addr, \
- section_offset, locsymcount, signed_p) \
- != TRUE) \
+ if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \
+ section_offset, isymbuf, locsymcount, \
+ signed_p)) \
return FALSE; \
if (signed_p) \
* result = op ((signed)a); \
@@ -7505,14 +7514,14 @@ eval_symbol (bfd_vma * result,
sym += strlen (#op); \
if (* sym == ':') \
++ sym; \
- if (eval_symbol (& a, sym, & sym, input_bfd, finfo, addr, \
- section_offset, locsymcount, signed_p) \
- != TRUE) \
+ if (!eval_symbol (&a, sym, &sym, input_bfd, finfo, addr, \
+ section_offset, isymbuf, locsymcount, \
+ signed_p)) \
return FALSE; \
++ sym; \
- if (eval_symbol (& b, sym, & sym, input_bfd, finfo, addr, \
- section_offset, locsymcount, signed_p) \
- != TRUE) \
+ if (!eval_symbol (&b, sym, &sym, input_bfd, finfo, addr, \
+ section_offset, isymbuf, locsymcount, \
+ signed_p)) \
return FALSE; \
if (signed_p) \
* result = ((signed) a) op ((signed) b); \
@@ -7555,8 +7564,9 @@ eval_symbol (bfd_vma * result,
/* Entry point to evaluator, called from elf_link_input_bfd. */
static bfd_boolean
-evaluate_complex_relocation_symbols (bfd * input_bfd,
- struct elf_final_link_info * finfo,
+evaluate_complex_relocation_symbols (bfd *input_bfd,
+ struct elf_final_link_info *finfo,
+ Elf_Internal_Sym *isymbuf,
size_t locsymcount)
{
const struct elf_backend_data * bed;
@@ -7626,7 +7636,7 @@ evaluate_complex_relocation_symbols (bfd * input_bfd,
if (index < locsymcount)
{
/* The symbol is local. */
- sym = finfo->internal_syms + index;
+ sym = isymbuf + index;
/* We're only processing STT_RELC or STT_SRELC type symbols. */
if ((ELF_ST_TYPE (sym->st_info) != STT_RELC) &&
@@ -7668,10 +7678,10 @@ evaluate_complex_relocation_symbols (bfd * input_bfd,
printf (" Evaluating '%s' ...\n ", sym_name);
#endif
if (eval_symbol (& result, sym_name, & sym_name, input_bfd,
- finfo, addr, section_offset, locsymcount,
+ finfo, addr, section_offset, isymbuf, locsymcount,
signed_p))
/* Symbol evaluated OK. Update to absolute value. */
- set_symbol_value (input_bfd, finfo, index, result);
+ set_symbol_value (input_bfd, isymbuf, locsymcount, index, result);
else
result = FALSE;
@@ -9066,15 +9076,6 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
if (isymbuf == NULL)
return FALSE;
}
- /* evaluate_complex_relocation_symbols looks for symbols in
- finfo->internal_syms. */
- else if (isymbuf != NULL && locsymcount != 0)
- {
- bfd_elf_get_elf_syms (input_bfd, symtab_hdr, locsymcount, 0,
- finfo->internal_syms,
- finfo->external_syms,
- finfo->locsym_shndx);
- }
/* Find local symbol sections and adjust values of symbols in
SEC_MERGE sections. Write out those local symbols we know are
@@ -9212,7 +9213,8 @@ elf_link_input_bfd (struct elf_final_link_info *finfo, bfd *input_bfd)
return FALSE;
}
- if (! evaluate_complex_relocation_symbols (input_bfd, finfo, locsymcount))
+ if (! evaluate_complex_relocation_symbols (input_bfd, finfo, isymbuf,
+ locsymcount))
return FALSE;
/* Relocate the contents of each section. */