* cofflink.c (process_embedded_commands): New function
reads and handles .drectve sections for PE. (coff_link_input_bfd): Call new function if PE.
This commit is contained in:
parent
0faa324790
commit
d25079a096
1 changed files with 351 additions and 17 deletions
368
bfd/cofflink.c
368
bfd/cofflink.c
|
@ -1,5 +1,5 @@
|
|||
/* COFF specific linker code.
|
||||
Copyright 1994 Free Software Foundation, Inc.
|
||||
Copyright 1994, 1995 Free Software Foundation, Inc.
|
||||
Written by Ian Lance Taylor, Cygnus Support.
|
||||
|
||||
This file is part of BFD, the Binary File Descriptor library.
|
||||
|
@ -78,6 +78,9 @@ struct coff_final_link_info
|
|||
bfd_byte *external_relocs;
|
||||
/* Buffer large enough to hold swapped relocs of any input section. */
|
||||
struct internal_reloc *internal_relocs;
|
||||
|
||||
enum bfd_link_subsystem subsystem;
|
||||
bfd_link_stack_heap stack_heap_parameters;
|
||||
};
|
||||
|
||||
static struct bfd_hash_entry *coff_link_hash_newfunc
|
||||
|
@ -100,6 +103,45 @@ static boolean coff_reloc_link_order
|
|||
PARAMS ((bfd *, struct coff_final_link_info *, asection *,
|
||||
struct bfd_link_order *));
|
||||
|
||||
|
||||
/* These new data and data types are used to keep track of the .idata$4 and
|
||||
.idata$5 relocations which are put into the .idata section for all of the
|
||||
*.dll input libraries linked in. This is not a great solution, and may
|
||||
break in the future if MS changes the format of its libraries, but it
|
||||
does work for the collection of mstools libraries we are currently working
|
||||
with. The main problem is that there are some new majic symbols defined
|
||||
in the libraries which are non-standard coff and simply aren't handled
|
||||
completely by ld. What has been included here will help finish up the job.
|
||||
Basically, during the link, .idata$4 and .idata$5 pointers are correctly
|
||||
relocated to the image. At the very end of the link, the .idata$2
|
||||
information is written. This data appears at the beginning of the .idata
|
||||
section and a 'set' of information appears for each *.dll passed in.
|
||||
Each set of information consists of 3 addresses, a pointer to the .idata$4
|
||||
start, a pointer to .idata$6 (which has the name of the dll), and a pointer
|
||||
to .idata$5 start. The idata$4 and 5 information is a list of pointers
|
||||
which appear to point to the name of various functions found within the dll.
|
||||
When invoked, the loader will write over these names with the correct
|
||||
addresses to use for these functions.
|
||||
Without this 'fix', all information appears correctly except for the
|
||||
addresses of the .idata$4 and 5 starts within the .idata$2 portion of the
|
||||
.idata section. What we will do is to keep track of the dll's processed
|
||||
and the number of functions needed from each dll. From this information
|
||||
we can correctly compute the start of the idata$4 and 5 lists for each
|
||||
dll in the idata section */
|
||||
static int num_DLLs_done = 0;
|
||||
static int num_DLLs = 0;
|
||||
static int all_entries = 0;
|
||||
struct DLL_struct {
|
||||
const char * DLL_name;
|
||||
int num_entries;
|
||||
};
|
||||
struct DLL_struct MS_DLL[10];
|
||||
static bfd_vma idata_4_prev = 0;
|
||||
static bfd_vma idata_5_prev = 0;
|
||||
static bfd_vma add_to_val = 0;
|
||||
|
||||
|
||||
|
||||
/* Create an entry in a COFF linker hash table. */
|
||||
|
||||
static struct bfd_hash_entry *
|
||||
|
@ -304,7 +346,7 @@ coff_read_string_table (abfd)
|
|||
else
|
||||
{
|
||||
#if STRING_SIZE_SIZE == 4
|
||||
strsize = bfd_h_get_32 (abfd, extstrsize);
|
||||
strsize = bfd_h_get_32 (abfd, (bfd_byte *) extstrsize);
|
||||
#else
|
||||
#error Change bfd_h_get_32
|
||||
#endif
|
||||
|
@ -566,9 +608,10 @@ coff_link_add_symbols (abfd, info)
|
|||
bfd_byte *eaux;
|
||||
union internal_auxent *iaux;
|
||||
|
||||
alloc = bfd_hash_allocate (&info->hash->table,
|
||||
(sym.n_numaux
|
||||
* sizeof (*alloc)));
|
||||
alloc = ((union internal_auxent *)
|
||||
bfd_hash_allocate (&info->hash->table,
|
||||
(sym.n_numaux
|
||||
* sizeof (*alloc))));
|
||||
if (alloc == NULL)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
|
@ -593,6 +636,126 @@ coff_link_add_symbols (abfd, info)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* parse out a -heap <reserved>,<commit> line */
|
||||
|
||||
static char *
|
||||
dores_com (ptr, def,res, com)
|
||||
char *ptr;
|
||||
int *def;
|
||||
int *res;
|
||||
int *com;
|
||||
{
|
||||
*def = 1;
|
||||
*res = strtoul (ptr, &ptr, 0);
|
||||
if (ptr[0] == ',')
|
||||
*com = strtoul (ptr+1, &ptr, 0);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static char *get_name(ptr, dst)
|
||||
char *ptr;
|
||||
char **dst;
|
||||
{
|
||||
while (*ptr == ' ')
|
||||
ptr++;
|
||||
*dst = ptr;
|
||||
while (*ptr && *ptr != ' ')
|
||||
ptr++;
|
||||
*ptr = 0;
|
||||
return ptr+1;
|
||||
}
|
||||
/* Process any magic embedded commands in a section called .drectve */
|
||||
|
||||
static int
|
||||
process_embedded_commands (abfd)
|
||||
bfd *abfd;
|
||||
{
|
||||
asection *sec = bfd_get_section_by_name (abfd, ".drectve");
|
||||
char *s;
|
||||
char *e;
|
||||
char *copy;
|
||||
if (!s)
|
||||
return 1;
|
||||
|
||||
copy = malloc (sec->_raw_size);
|
||||
if (!copy)
|
||||
{
|
||||
bfd_set_error (bfd_error_no_memory);
|
||||
return 0;
|
||||
}
|
||||
if (! bfd_get_section_contents(abfd, sec, copy, 0, sec->_raw_size))
|
||||
{
|
||||
free (copy);
|
||||
return 0;
|
||||
}
|
||||
e = copy + sec->_raw_size;
|
||||
for (s = copy; s < e ; )
|
||||
{
|
||||
if (s[0]!= '-') {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
if (strncmp (s,"-attr", 5) == 0)
|
||||
{
|
||||
char *name;
|
||||
char *attribs;
|
||||
asection *asec;
|
||||
|
||||
int loop = 1;
|
||||
int had_write = 0;
|
||||
int had_read = 0;
|
||||
int had_exec= 0;
|
||||
int had_shared= 0;
|
||||
s += 5;
|
||||
s = get_name(s, &name);
|
||||
s = get_name(s, &attribs);
|
||||
while (loop) {
|
||||
switch (*attribs++)
|
||||
{
|
||||
case 'W':
|
||||
had_write = 1;
|
||||
break;
|
||||
case 'R':
|
||||
had_read = 1;
|
||||
break;
|
||||
case 'S':
|
||||
had_shared = 1;
|
||||
break;
|
||||
case 'X':
|
||||
had_exec = 1;
|
||||
break;
|
||||
default:
|
||||
loop = 0;
|
||||
}
|
||||
}
|
||||
asec = bfd_get_section_by_name (abfd, name);
|
||||
if (asec) {
|
||||
if (had_exec)
|
||||
asec->flags |= SEC_CODE;
|
||||
if (!had_write)
|
||||
asec->flags |= SEC_READONLY;
|
||||
}
|
||||
}
|
||||
else if (strncmp (s,"-heap", 5) == 0)
|
||||
{
|
||||
s = dores_com (s+5,
|
||||
&NT_stack_heap.heap_defined,
|
||||
&NT_stack_heap.heap_reserve,
|
||||
&NT_stack_heap.heap_commit);
|
||||
}
|
||||
else if (strncmp (s,"-stack", 6) == 0)
|
||||
{
|
||||
s = dores_com (s+6,
|
||||
&NT_stack_heap.heap_defined,
|
||||
&NT_stack_heap.heap_reserve,
|
||||
&NT_stack_heap.heap_commit);
|
||||
}
|
||||
else
|
||||
s++;
|
||||
}
|
||||
free (copy);
|
||||
return 1;
|
||||
}
|
||||
/* Do the final link step. */
|
||||
|
||||
boolean
|
||||
|
@ -633,6 +796,15 @@ _bfd_coff_final_link (abfd, info)
|
|||
finfo.external_relocs = NULL;
|
||||
finfo.internal_relocs = NULL;
|
||||
|
||||
if (obj_pe(abfd))
|
||||
{
|
||||
/* store the subsystem, stack and heap parameters in variables defined
|
||||
in internal.h so that when they are needed to write the NT optional
|
||||
file header (coffcode.h), they will be available */
|
||||
NT_subsystem = info->subsystem;
|
||||
NT_stack_heap = info->stack_heap_parameters;
|
||||
}
|
||||
|
||||
finfo.strtab = _bfd_stringtab_init ();
|
||||
if (finfo.strtab == NULL)
|
||||
goto error_return;
|
||||
|
@ -989,7 +1161,7 @@ _bfd_coff_final_link (abfd, info)
|
|||
#if STRING_SIZE_SIZE == 4
|
||||
bfd_h_put_32 (abfd,
|
||||
_bfd_stringtab_size (finfo.strtab) + STRING_SIZE_SIZE,
|
||||
strbuf);
|
||||
(bfd_byte *) strbuf);
|
||||
#else
|
||||
#error Change bfd_h_put_32
|
||||
#endif
|
||||
|
@ -1054,6 +1226,9 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
bfd *input_bfd;
|
||||
{
|
||||
boolean (*sym_is_global) PARAMS ((bfd *, struct internal_syment *));
|
||||
boolean (*adjust_symndx) PARAMS ((bfd *, struct bfd_link_info *, bfd *,
|
||||
asection *, struct internal_reloc *,
|
||||
boolean *));
|
||||
bfd *output_bfd;
|
||||
const char *strings;
|
||||
bfd_size_type syment_base;
|
||||
|
@ -1109,6 +1284,13 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
indexp = finfo->sym_indices;
|
||||
output_index = syment_base;
|
||||
outsym = finfo->outsyms;
|
||||
|
||||
if (obj_pe (output_bfd))
|
||||
{
|
||||
if (!process_embedded_commands (input_bfd))
|
||||
return false;
|
||||
}
|
||||
|
||||
while (esym < esym_end)
|
||||
{
|
||||
struct internal_syment isym;
|
||||
|
@ -1387,7 +1569,8 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
{
|
||||
/* If this is a long filename, we must put it in the
|
||||
string table. */
|
||||
if (auxp->x_file.x_n.x_zeroes == 0)
|
||||
if (auxp->x_file.x_n.x_zeroes == 0
|
||||
&& auxp->x_file.x_n.x_offset != 0)
|
||||
{
|
||||
const char *filename;
|
||||
bfd_size_type indx;
|
||||
|
@ -1570,13 +1753,14 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
symbol will be the first symbol in the next input file. In the
|
||||
normal case, this will save us from writing out the C_FILE symbol
|
||||
again. */
|
||||
if (finfo->last_file_index >= syment_base)
|
||||
if (finfo->last_file_index != -1
|
||||
&& finfo->last_file_index >= syment_base)
|
||||
{
|
||||
finfo->last_file.n_value = output_index;
|
||||
bfd_coff_swap_sym_out (output_bfd, (PTR) &finfo->last_file,
|
||||
(PTR) (finfo->outsyms
|
||||
+ ((finfo->last_file_index - syment_base)
|
||||
* osymesz)));
|
||||
+ ((finfo->last_file_index - syment_base)
|
||||
* osymesz)));
|
||||
}
|
||||
|
||||
/* Write the modified symbols to the output file. */
|
||||
|
@ -1598,6 +1782,7 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
|
||||
/* Relocate the contents of each section. */
|
||||
relsz = bfd_coff_relsz (input_bfd);
|
||||
adjust_symndx = coff_backend_info (input_bfd)->_bfd_coff_adjust_symndx;
|
||||
for (o = input_bfd->sections; o != NULL; o = o->next)
|
||||
{
|
||||
if ((o->flags & SEC_HAS_CONTENTS) == 0)
|
||||
|
@ -1605,7 +1790,7 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
|
||||
if (! bfd_get_section_contents (input_bfd, o, finfo->contents,
|
||||
(file_ptr) 0, o->_raw_size))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
if ((o->flags & SEC_RELOC) != 0)
|
||||
{
|
||||
|
@ -1655,7 +1840,6 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
struct coff_link_hash_entry **rel_hash;
|
||||
|
||||
offset = o->output_section->vma + o->output_offset - o->vma;
|
||||
|
||||
irel = internal_relocs;
|
||||
irelend = irel + o->reloc_count;
|
||||
rel_hash = (finfo->section_info[target_index].rel_hashes
|
||||
|
@ -1663,6 +1847,7 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
for (; irel < irelend; irel++, rel_hash++)
|
||||
{
|
||||
struct coff_link_hash_entry *h;
|
||||
boolean adjusted;
|
||||
|
||||
*rel_hash = NULL;
|
||||
|
||||
|
@ -1673,6 +1858,16 @@ coff_link_input_bfd (finfo, input_bfd)
|
|||
if (irel->r_symndx == -1)
|
||||
continue;
|
||||
|
||||
if (adjust_symndx)
|
||||
{
|
||||
if (! (*adjust_symndx) (output_bfd, finfo->info,
|
||||
input_bfd, o, irel,
|
||||
&adjusted))
|
||||
return false;
|
||||
if (adjusted)
|
||||
continue;
|
||||
}
|
||||
|
||||
h = obj_coff_sym_hashes (input_bfd)[irel->r_symndx];
|
||||
if (h != NULL)
|
||||
{
|
||||
|
@ -1792,12 +1987,13 @@ coff_write_global_sym (h, data)
|
|||
return false;
|
||||
|
||||
case bfd_link_hash_undefined:
|
||||
case bfd_link_hash_weak:
|
||||
case bfd_link_hash_undefweak:
|
||||
isym.n_scnum = N_UNDEF;
|
||||
isym.n_value = 0;
|
||||
break;
|
||||
|
||||
case bfd_link_hash_defined:
|
||||
case bfd_link_hash_defweak:
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
|
@ -1897,7 +2093,7 @@ coff_reloc_link_order (output_bfd, finfo, output_section, link_order)
|
|||
asection *output_section;
|
||||
struct bfd_link_order *link_order;
|
||||
{
|
||||
const reloc_howto_type *howto;
|
||||
reloc_howto_type *howto;
|
||||
struct internal_reloc *irel;
|
||||
struct coff_link_hash_entry **rel_hash_ptr;
|
||||
|
||||
|
@ -2039,6 +2235,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
|
|||
struct internal_reloc *rel;
|
||||
struct internal_reloc *relend;
|
||||
|
||||
|
||||
rel = relocs;
|
||||
relend = rel + input_section->reloc_count;
|
||||
for (; rel < relend; rel++)
|
||||
|
@ -2048,7 +2245,7 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
|
|||
struct internal_syment *sym;
|
||||
bfd_vma addend;
|
||||
bfd_vma val;
|
||||
const reloc_howto_type *howto;
|
||||
reloc_howto_type *howto;
|
||||
bfd_reloc_status_type rstat;
|
||||
|
||||
symndx = rel->r_symndx;
|
||||
|
@ -2068,21 +2265,33 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
|
|||
size of the symbol is included in the section contents, or it
|
||||
is not. We assume that the size is not included, and force
|
||||
the rtype_to_howto function to adjust the addend as needed. */
|
||||
|
||||
if (sym != NULL && sym->n_scnum != 0)
|
||||
addend = - sym->n_value;
|
||||
else
|
||||
addend = 0;
|
||||
|
||||
|
||||
howto = bfd_coff_rtype_to_howto (input_bfd, input_section, rel, h,
|
||||
sym, &addend);
|
||||
if (howto == NULL)
|
||||
return false;
|
||||
|
||||
/* WINDOWS_NT; in this next section, the value of 'val' will be computed.
|
||||
With respect to the .idata and .rsrc sections, the NT_IMAGE_BASE
|
||||
must be removed from the value that is to be relocated (NT_IMAGE_BASE
|
||||
is currently defined in internal.h and has value 400000). Now this
|
||||
value should only be removed from addresses being relocated in the
|
||||
.idata and .rsrc sections, not the .text section which should have
|
||||
the 'real' address. In addition, the .rsrc val's must also be
|
||||
adjusted by the input_section->vma. */
|
||||
|
||||
val = 0;
|
||||
|
||||
if (h == NULL)
|
||||
{
|
||||
asection *sec;
|
||||
int i;
|
||||
|
||||
if (symndx == -1)
|
||||
{
|
||||
|
@ -2092,15 +2301,30 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
|
|||
else
|
||||
{
|
||||
sec = sections[symndx];
|
||||
val = (sec->output_section->vma
|
||||
val = (sec->output_section->vma
|
||||
+ sec->output_offset
|
||||
+ sym->n_value
|
||||
- sec->vma);
|
||||
if (obj_pe(output_bfd)) {
|
||||
/* Make a correction here to val if the sec is either .rsrc
|
||||
or .idata */
|
||||
if (strcmp (input_section->name, ".text") != 0)
|
||||
{
|
||||
if (strncmp (sec->name, ".idata$", 7) == 0)
|
||||
val -= NT_IMAGE_BASE;
|
||||
else if (strncmp (sec->name, ".rsrc$", 6) == 0)
|
||||
{
|
||||
val -= NT_IMAGE_BASE;
|
||||
val += sec->vma;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h->root.type == bfd_link_hash_defined)
|
||||
if (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak)
|
||||
{
|
||||
asection *sec;
|
||||
|
||||
|
@ -2108,6 +2332,20 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
|
|||
val = (h->root.u.def.value
|
||||
+ sec->output_section->vma
|
||||
+ sec->output_offset);
|
||||
if (obj_pe (output_bfd)) {
|
||||
/* Make a correction here to val if the sec is either .rsrc
|
||||
or .idata */
|
||||
if (strcmp (input_section->name, ".text") != 0)
|
||||
{
|
||||
if (strncmp (sec->name, ".idata$", 7) == 0)
|
||||
val -= NT_IMAGE_BASE;
|
||||
else if (strncmp (sec->name, ".rsrc$", 6) == 0)
|
||||
{
|
||||
val -= NT_IMAGE_BASE;
|
||||
val += sec->vma;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (! info->relocateable)
|
||||
{
|
||||
|
@ -2118,6 +2356,102 @@ _bfd_coff_generic_relocate_section (output_bfd, info, input_bfd,
|
|||
}
|
||||
}
|
||||
|
||||
if (obj_pe (output_bfd)) {
|
||||
|
||||
/* Here's where we will collect the information about the dll .idata$4
|
||||
and 5 entries and fix up the vals for .idata$2 information. When
|
||||
we encounter processing for .idata$5 (this could also be done for
|
||||
.idata$4) we will keep track of the number of entries made for a
|
||||
particular dll. Now if we are processing .idata$2 input_section,
|
||||
then we know how many entries have been made from each dll and we
|
||||
have to fix up the .idata$2 start addresses for .idata$4 and
|
||||
.idata$5. */
|
||||
add_to_val = 0;
|
||||
if (strncmp (input_section->name, ".idata$5", 8) == 0)
|
||||
{
|
||||
if (num_DLLs == 0) /* this is the first one */
|
||||
{
|
||||
num_DLLs += 1;
|
||||
MS_DLL[num_DLLs].DLL_name = input_bfd->filename;
|
||||
MS_DLL[num_DLLs].num_entries += 1;
|
||||
}
|
||||
else if (!strcmp (input_bfd->filename, MS_DLL[num_DLLs].DLL_name))
|
||||
{
|
||||
/* this is just another entry */
|
||||
MS_DLL[num_DLLs].num_entries += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is a new DLL */
|
||||
num_DLLs += 1;
|
||||
MS_DLL[num_DLLs].DLL_name = input_bfd->filename;
|
||||
MS_DLL[num_DLLs].num_entries += 1;
|
||||
}
|
||||
all_entries += 1;
|
||||
}
|
||||
|
||||
else if (strncmp (input_section->name, ".idata$2", 8) == 0)
|
||||
{
|
||||
/* All information about the number of entries needed from each
|
||||
DLL has been collected at this point. Now we actually want to
|
||||
make and adjustment to the val's for .idata$4 and .idata$5
|
||||
which are part of the .idata$2 section. */
|
||||
/* first we have to get the symbol name from sym. This will be
|
||||
either .idata$4, .idata$5 or .idata$6. A 'fixup' is computed for
|
||||
.idata$4 and .idata$5 but not for .idata$6 (this value is handled
|
||||
correctly already and doesn't have to be fixed) */
|
||||
const char *name;
|
||||
char buf[SYMNMLEN + 1];
|
||||
|
||||
if (sym->_n._n_n._n_zeroes == 0 && sym->_n._n_n._n_offset != 0)
|
||||
name = obj_coff_strings (input_bfd) + sym->_n._n_n._n_offset;
|
||||
else
|
||||
{
|
||||
strncpy (buf, sym->_n._n_name, SYMNMLEN);
|
||||
buf[SYMNMLEN] = '\0';
|
||||
name = buf;
|
||||
}
|
||||
|
||||
if (num_DLLs_done)
|
||||
{
|
||||
/* we have done at least one. The val fixups are based on the
|
||||
previous fixups */
|
||||
if (strncmp (name, ".idata$4", 8) == 0)
|
||||
{
|
||||
add_to_val = idata_4_prev +
|
||||
((MS_DLL[num_DLLs_done].num_entries + 1) * 4);
|
||||
idata_4_prev = add_to_val;
|
||||
}
|
||||
else if (strncmp (name, ".idata$5", 8) == 0)
|
||||
{
|
||||
add_to_val = idata_5_prev +
|
||||
((MS_DLL[num_DLLs_done].num_entries + 1) * 4);
|
||||
idata_5_prev = add_to_val;
|
||||
num_DLLs_done += 1; /* assuming that idata$5 is done after $4*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This is the first one. The other idata$4 and 5 entries will be
|
||||
computed from these */
|
||||
if (strncmp (name, ".idata$4", 8) == 0)
|
||||
{
|
||||
add_to_val = ((num_DLLs - 1) * 0x14) + 0x28;
|
||||
idata_4_prev = add_to_val;
|
||||
}
|
||||
else if (strncmp (name, ".idata$5", 8) == 0)
|
||||
{
|
||||
add_to_val = idata_4_prev + (all_entries + num_DLLs) * 4;
|
||||
idata_5_prev = add_to_val;
|
||||
num_DLLs_done += 1; /* assuming that idata$5 is done after $4*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
val = val + add_to_val;
|
||||
|
||||
}
|
||||
|
||||
rstat = _bfd_final_link_relocate (howto, input_bfd, input_section,
|
||||
contents,
|
||||
rel->r_vaddr - input_section->vma,
|
||||
|
|
Loading…
Add table
Reference in a new issue