mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-10-13 02:45:02 +08:00
xcoff: implement linker relaxation
bfd/ChangeLog: * coff-rs6000.c (xcoff_reloc_type_noop): Add info argument. (xcoff_reloc_type_fail): Likewise. (xcoff_reloc_type_pos): Likewise. (xcoff_reloc_type_neg): Likewise. (xcoff_reloc_type_rel): Likewise. (xcoff_reloc_type_toc): Likewise. (xcoff_reloc_type_ba): Likewise. (xcoff_reloc_type_crel): Likewise. (xcoff_reloc_type_tls): Likewise. (xcoff_reloc_type_br): Add stub handler. (xcoff_ppc_relocate_section): Add info to xcoff_calculate_relocation. (xcoff_stub_indirect_call_code): New constant. (xcoff_stub_shared_call_code): Likewise. (bfd_xcoff_backend_data): Add stub code fields. (bfd_pmac_xcoff_backend_data): Likewise. * coff64-rs6000.c (xcoff64_reloc_type_br): Add stub handler. (xcoff64_ppc_relocate_section): Add info to xcoff64_calculate_relocation. (xcoff64_stub_indirect_call_code): New constant. (xcoff64_stub_shared_call_code): Likewise. (bfd_xcoff_backend_data): Add stub code fields. (bfd_xcoff_aix5_backend_data): Likewise. * libxcoff.h (struct xcoff_backend_data_rec): Add stub fields. (bfd_xcoff_stub_indirect_call_code): New define. (bfd_xcoff_stub_indirect_call_size): New define. (bfd_xcoff_stub_shared_call_code): New define. (bfd_xcoff_stub_shared_call_size): New define. (xcoff_reloc_function): Add info argument. (enum xcoff_stub_type): New enum. (struct xcoff_stub_hash_entry): New structure. * xcofflink.c (struct xcoff_link_hash_table): Add stub hash table and params fields. (xcoff_stub_hash_entry): New define. (xcoff_stub_hash_lookup): New define. (stub_hash_newfunc): New function. (_bfd_xcoff_bfd_link_hash_table_free): Free the new stub hash table. (_bfd_xcoff_bfd_link_hash_table_create): Create the new stub hash table. (xcoff_link_add_symbols): Save rawsize for XTY_SD. (bfd_xcoff_link_init): New function. (xcoff_stub_csect_name): New function. (xcoff_stub_get_csect_in_range): New function. (xcoff_stub_name): New function. (bfd_xcoff_get_stub_entry): New function. (bfd_xcoff_type_of_stub): New function. (xcoff_add_stub): New function. (xcoff_build_one_stub): New function. (bfd_xcoff_size_stubs): New function. (bfd_xcoff_build_stubs): New function. (xcoff_stub_create_relocations): New function. (xcoff_link_input_bfd): Adapt relocations to stub. (xcoff_write_global_symbol): Adapt to new TOC entries generated for stubs. (_bfd_xcoff_bfd_final_link): Handle stub file. * xcofflink.h (struct bfd_xcoff_link_params): New structure. ld/ChangeLog: * emultempl/aix.em (params): New variable. (stub_file): New variable. (xcoff_add_stub_section): New function. (xcoff_layout_sections_again): New function (hook_in_stub): New function. (_after_allocation): Add stub creation. (_create_output_section_statements): Allocate stub file and pass params to backend.
This commit is contained in:

committed by
Nick Clifton

parent
1876a54217
commit
2d23f9656c
@ -1,3 +1,63 @@
|
||||
2022-04-20 Clément Chigot <clement.chigot@atos.net>
|
||||
|
||||
* coff-rs6000.c (xcoff_reloc_type_noop): Add info argument.
|
||||
(xcoff_reloc_type_fail): Likewise.
|
||||
(xcoff_reloc_type_pos): Likewise.
|
||||
(xcoff_reloc_type_neg): Likewise.
|
||||
(xcoff_reloc_type_rel): Likewise.
|
||||
(xcoff_reloc_type_toc): Likewise.
|
||||
(xcoff_reloc_type_ba): Likewise.
|
||||
(xcoff_reloc_type_crel): Likewise.
|
||||
(xcoff_reloc_type_tls): Likewise.
|
||||
(xcoff_reloc_type_br): Add stub handler.
|
||||
(xcoff_ppc_relocate_section): Add info to
|
||||
xcoff_calculate_relocation.
|
||||
(xcoff_stub_indirect_call_code): New constant.
|
||||
(xcoff_stub_shared_call_code): Likewise.
|
||||
(bfd_xcoff_backend_data): Add stub code fields.
|
||||
(bfd_pmac_xcoff_backend_data): Likewise.
|
||||
* coff64-rs6000.c (xcoff64_reloc_type_br): Add stub handler.
|
||||
(xcoff64_ppc_relocate_section): Add info to
|
||||
xcoff64_calculate_relocation.
|
||||
(xcoff64_stub_indirect_call_code): New constant.
|
||||
(xcoff64_stub_shared_call_code): Likewise.
|
||||
(bfd_xcoff_backend_data): Add stub code fields.
|
||||
(bfd_xcoff_aix5_backend_data): Likewise.
|
||||
* libxcoff.h (struct xcoff_backend_data_rec): Add stub fields.
|
||||
(bfd_xcoff_stub_indirect_call_code): New define.
|
||||
(bfd_xcoff_stub_indirect_call_size): New define.
|
||||
(bfd_xcoff_stub_shared_call_code): New define.
|
||||
(bfd_xcoff_stub_shared_call_size): New define.
|
||||
(xcoff_reloc_function): Add info argument.
|
||||
(enum xcoff_stub_type): New enum.
|
||||
(struct xcoff_stub_hash_entry): New structure.
|
||||
* xcofflink.c (struct xcoff_link_hash_table): Add stub hash
|
||||
table and params fields.
|
||||
(xcoff_stub_hash_entry): New define.
|
||||
(xcoff_stub_hash_lookup): New define.
|
||||
(stub_hash_newfunc): New function.
|
||||
(_bfd_xcoff_bfd_link_hash_table_free): Free the new stub hash
|
||||
table.
|
||||
(_bfd_xcoff_bfd_link_hash_table_create): Create the new stub
|
||||
hash table.
|
||||
(xcoff_link_add_symbols): Save rawsize for XTY_SD.
|
||||
(bfd_xcoff_link_init): New function.
|
||||
(xcoff_stub_csect_name): New function.
|
||||
(xcoff_stub_get_csect_in_range): New function.
|
||||
(xcoff_stub_name): New function.
|
||||
(bfd_xcoff_get_stub_entry): New function.
|
||||
(bfd_xcoff_type_of_stub): New function.
|
||||
(xcoff_add_stub): New function.
|
||||
(xcoff_build_one_stub): New function.
|
||||
(bfd_xcoff_size_stubs): New function.
|
||||
(bfd_xcoff_build_stubs): New function.
|
||||
(xcoff_stub_create_relocations): New function.
|
||||
(xcoff_link_input_bfd): Adapt relocations to stub.
|
||||
(xcoff_write_global_symbol): Adapt to new TOC entries generated
|
||||
for stubs.
|
||||
(_bfd_xcoff_bfd_final_link): Handle stub file.
|
||||
* xcofflink.h (struct bfd_xcoff_link_params): New structure.
|
||||
|
||||
2022-04-20 Clément Chigot <clement.chigot@atos.net>
|
||||
|
||||
* coff-rs6000.c (_bfd_xcoff_put_ldsymbol_name): Write len in
|
||||
|
@ -2937,7 +2937,8 @@ xcoff_reloc_type_noop (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val ATTRIBUTE_UNUSED,
|
||||
bfd_vma addend ATTRIBUTE_UNUSED,
|
||||
bfd_vma *relocation ATTRIBUTE_UNUSED,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -2952,7 +2953,8 @@ xcoff_reloc_type_fail (bfd *input_bfd,
|
||||
bfd_vma val ATTRIBUTE_UNUSED,
|
||||
bfd_vma addend ATTRIBUTE_UNUSED,
|
||||
bfd_vma *relocation ATTRIBUTE_UNUSED,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
_bfd_error_handler
|
||||
/* xgettext: c-format */
|
||||
@ -2972,7 +2974,8 @@ xcoff_reloc_type_pos (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
*relocation = val + addend;
|
||||
return true;
|
||||
@ -2988,7 +2991,8 @@ xcoff_reloc_type_neg (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
*relocation = - val - addend;
|
||||
return true;
|
||||
@ -3004,7 +3008,8 @@ xcoff_reloc_type_rel (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
howto->pc_relative = true;
|
||||
|
||||
@ -3027,7 +3032,8 @@ xcoff_reloc_type_toc (bfd *input_bfd,
|
||||
bfd_vma val,
|
||||
bfd_vma addend ATTRIBUTE_UNUSED,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct xcoff_link_hash_entry *h;
|
||||
|
||||
@ -3076,7 +3082,8 @@ xcoff_reloc_type_ba (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
howto->src_mask &= ~3;
|
||||
howto->dst_mask = howto->src_mask;
|
||||
@ -3096,10 +3103,13 @@ xcoff_reloc_type_br (bfd *input_bfd,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents)
|
||||
bfd_byte *contents,
|
||||
struct bfd_link_info *info)
|
||||
{
|
||||
struct xcoff_link_hash_entry *h;
|
||||
bfd_vma section_offset;
|
||||
struct xcoff_stub_hash_entry *stub_entry = NULL;
|
||||
enum xcoff_stub_type stub_type;
|
||||
|
||||
if (0 > rel->r_symndx)
|
||||
return false;
|
||||
@ -3153,6 +3163,27 @@ xcoff_reloc_type_br (bfd *input_bfd,
|
||||
howto->complain_on_overflow = complain_overflow_dont;
|
||||
}
|
||||
|
||||
/* Check if a stub is needed. */
|
||||
stub_type = bfd_xcoff_type_of_stub (input_section, rel, val, h);
|
||||
if (stub_type != xcoff_stub_none)
|
||||
{
|
||||
asection *stub_csect;
|
||||
|
||||
stub_entry = bfd_xcoff_get_stub_entry (input_section, h, info);
|
||||
if (stub_entry == NULL)
|
||||
{
|
||||
_bfd_error_handler (_("Unable to find the stub entry targeting %s"),
|
||||
h->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
stub_csect = stub_entry->hcsect->root.u.def.section;
|
||||
val = (stub_entry->stub_offset
|
||||
+ stub_csect->output_section->vma
|
||||
+ stub_csect->output_offset);
|
||||
}
|
||||
|
||||
/* The original PC-relative relocation is biased by -r_vaddr, so adding
|
||||
the value below will give the absolute target address. */
|
||||
*relocation = val + addend + rel->r_vaddr;
|
||||
@ -3202,7 +3233,8 @@ xcoff_reloc_type_crel (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val ATTRIBUTE_UNUSED,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
howto->pc_relative = true;
|
||||
howto->src_mask &= ~3;
|
||||
@ -3227,7 +3259,8 @@ xcoff_reloc_type_tls (bfd *input_bfd ATTRIBUTE_UNUSED,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED)
|
||||
bfd_byte *contents ATTRIBUTE_UNUSED,
|
||||
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct xcoff_link_hash_entry *h;
|
||||
|
||||
@ -3763,7 +3796,7 @@ xcoff_ppc_relocate_section (bfd *output_bfd,
|
||||
if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
|
||||
|| !((*xcoff_calculate_relocation[rel->r_type])
|
||||
(input_bfd, input_section, output_bfd, rel, sym, &howto, val,
|
||||
addend, &relocation, contents)))
|
||||
addend, &relocation, contents, info)))
|
||||
return false;
|
||||
|
||||
/* address */
|
||||
@ -4281,6 +4314,34 @@ HOWTO (0, /* type */
|
||||
0xffffffff, /* dst_mask */
|
||||
false); /* pcrel_offset */
|
||||
|
||||
/* Indirect call stub
|
||||
The first word of the code must be modified by filling in
|
||||
the correct TOC offset. */
|
||||
|
||||
static const unsigned long xcoff_stub_indirect_call_code[4] =
|
||||
{
|
||||
0x81820000, /* lwz r12,0(r2) */
|
||||
0x800c0000, /* lwz r0,0(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
/* Shared call stub
|
||||
The first word of the code must be modified by filling in
|
||||
the correct TOC offset.
|
||||
This is exactly as the glink code but without the traceback,
|
||||
as it won't be an independent function. */
|
||||
|
||||
static const unsigned long xcoff_stub_shared_call_code[6] =
|
||||
{
|
||||
0x81820000, /* lwz r12,0(r2) */
|
||||
0x90410014, /* stw r2,20(r1) */
|
||||
0x800c0000, /* lwz r0,0(r12) */
|
||||
0x804c0004, /* lwz r2,4(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
/* glink
|
||||
|
||||
The first word of global linkage code must be modified by filling in
|
||||
@ -4497,6 +4558,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
|
||||
/* rtinit */
|
||||
64, /* _xcoff_rtinit_size */
|
||||
xcoff_generate_rtinit,
|
||||
|
||||
/* Stub indirect call. */
|
||||
&xcoff_stub_indirect_call_code[0],
|
||||
16, /* _xcoff_stub_indirect_call_size */
|
||||
|
||||
/* Stub shared call. */
|
||||
&xcoff_stub_shared_call_code[0],
|
||||
24, /* _xcoff_stub_shared_call_size */
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
@ -4679,6 +4748,14 @@ static const struct xcoff_backend_data_rec bfd_pmac_xcoff_backend_data =
|
||||
/* rtinit */
|
||||
0, /* _xcoff_rtinit_size */
|
||||
xcoff_generate_rtinit,
|
||||
|
||||
/* Stub indirect call. */
|
||||
&xcoff_stub_indirect_call_code[0],
|
||||
16, /* _xcoff_stub_indirect_call_size */
|
||||
|
||||
/* Stub shared call. */
|
||||
&xcoff_stub_shared_call_code[0],
|
||||
24, /* _xcoff_stub_shared_call_size */
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
|
@ -778,10 +778,13 @@ xcoff64_reloc_type_br (bfd *input_bfd,
|
||||
bfd_vma val,
|
||||
bfd_vma addend,
|
||||
bfd_vma *relocation,
|
||||
bfd_byte *contents)
|
||||
bfd_byte *contents,
|
||||
struct bfd_link_info *info)
|
||||
{
|
||||
struct xcoff_link_hash_entry *h;
|
||||
bfd_vma section_offset;
|
||||
struct xcoff_stub_hash_entry *stub_entry = NULL;
|
||||
enum xcoff_stub_type stub_type;
|
||||
|
||||
if (0 > rel->r_symndx)
|
||||
return false;
|
||||
@ -833,6 +836,27 @@ xcoff64_reloc_type_br (bfd *input_bfd,
|
||||
howto->complain_on_overflow = complain_overflow_dont;
|
||||
}
|
||||
|
||||
/* Check if a stub is needed. */
|
||||
stub_type = bfd_xcoff_type_of_stub (input_section, rel, val, h);
|
||||
if (stub_type != xcoff_stub_none)
|
||||
{
|
||||
asection *stub_csect;
|
||||
|
||||
stub_entry = bfd_xcoff_get_stub_entry (input_section, h, info);
|
||||
if (stub_entry == NULL)
|
||||
{
|
||||
_bfd_error_handler (_("Unable to find the stub entry targeting %s"),
|
||||
h->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
return false;
|
||||
}
|
||||
|
||||
stub_csect = stub_entry->hcsect->root.u.def.section;
|
||||
val = (stub_entry->stub_offset
|
||||
+ stub_csect->output_section->vma
|
||||
+ stub_csect->output_offset);
|
||||
}
|
||||
|
||||
/* The original PC-relative relocation is biased by -r_vaddr, so adding
|
||||
the value below will give the absolute target address. */
|
||||
*relocation = val + addend + rel->r_vaddr;
|
||||
@ -1645,7 +1669,7 @@ xcoff64_ppc_relocate_section (bfd *output_bfd,
|
||||
if (rel->r_type >= XCOFF_MAX_CALCULATE_RELOCATION
|
||||
|| !((*xcoff64_calculate_relocation[rel->r_type])
|
||||
(input_bfd, input_section, output_bfd, rel, sym, &howto, val,
|
||||
addend, &relocation, contents)))
|
||||
addend, &relocation, contents, info)))
|
||||
return false;
|
||||
|
||||
/* address */
|
||||
@ -2386,12 +2410,32 @@ HOWTO (0, /* type */
|
||||
MINUS_ONE, /* dst_mask */
|
||||
false); /* pcrel_offset */
|
||||
|
||||
/* Indirect call stub */
|
||||
static const unsigned long xcoff64_stub_indirect_call_code[4] =
|
||||
{
|
||||
0xe9820000, /* ld r12,0(r2) */
|
||||
0xe80c0000, /* ld r0,0(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
/* Shared call stub */
|
||||
static const unsigned long xcoff64_stub_shared_call_code[6] =
|
||||
{
|
||||
0xe9820000, /* ld r12,0(r2) */
|
||||
0xf8410028, /* std r2,40(r1) */
|
||||
0xe80c0000, /* ld r0,0(r12) */
|
||||
0xe84c0008, /* ld r2,8(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
};
|
||||
|
||||
static const unsigned long xcoff64_glink_code[10] =
|
||||
{
|
||||
0xe9820000, /* ld r12,0(r2) */
|
||||
0xf8410028, /* std r2,40(r1) */
|
||||
0xe80c0000, /* ld r0,0(r12) */
|
||||
0xe84c0008, /* ld r0,8(r12) */
|
||||
0xe84c0008, /* ld r2,8(r12) */
|
||||
0x7c0903a6, /* mtctr r0 */
|
||||
0x4e800420, /* bctr */
|
||||
0x00000000, /* start of traceback table */
|
||||
@ -2495,6 +2539,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_backend_data =
|
||||
/* rtinit. */
|
||||
88, /* _xcoff_rtinit_size */
|
||||
xcoff64_generate_rtinit,
|
||||
|
||||
/* Stub indirect call. */
|
||||
&xcoff64_stub_indirect_call_code[0],
|
||||
16, /* _xcoff_stub_indirect_call_size */
|
||||
|
||||
/* Stub shared call. */
|
||||
&xcoff64_stub_shared_call_code[0],
|
||||
24, /* _xcoff_stub_shared_call_size */
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
@ -2759,6 +2811,14 @@ static const struct xcoff_backend_data_rec bfd_xcoff_aix5_backend_data =
|
||||
/* rtinit. */
|
||||
88, /* _xcoff_rtinit_size */
|
||||
xcoff64_generate_rtinit,
|
||||
|
||||
/* Stub indirect call. */
|
||||
&xcoff64_stub_indirect_call_code[0],
|
||||
16, /* _xcoff_stub_indirect_call_size */
|
||||
|
||||
/* Stub shared call. */
|
||||
&xcoff64_stub_shared_call_code[0],
|
||||
24, /* _xcoff_stub_shared_call_size */
|
||||
};
|
||||
|
||||
/* The transfer vector that leads the outside world to all of the above. */
|
||||
|
@ -99,6 +99,15 @@ struct xcoff_backend_data_rec
|
||||
unsigned int _xcoff_rtinit_size;
|
||||
bool (*_xcoff_generate_rtinit)
|
||||
(bfd *, const char *, const char *, bool);
|
||||
|
||||
/* Stubs code generation.
|
||||
The code part is an array which might need to be modified by
|
||||
some relocations.
|
||||
The size is in bytes. */
|
||||
const unsigned long *_xcoff_stub_indirect_call_code;
|
||||
unsigned long _xcoff_stub_indirect_call_size;
|
||||
const unsigned long *_xcoff_stub_shared_call_code;
|
||||
unsigned long _xcoff_stub_shared_call_size;
|
||||
};
|
||||
|
||||
/* Look up an entry in an XCOFF link hash table. */
|
||||
@ -185,6 +194,11 @@ struct xcoff_backend_data_rec
|
||||
#define bfd_xcoff_glink_code(a, b) ((xcoff_backend (a)->_xcoff_glink_code[(b)]))
|
||||
#define bfd_xcoff_glink_code_size(a) ((xcoff_backend (a)->_xcoff_glink_size))
|
||||
|
||||
#define bfd_xcoff_stub_indirect_call_code(a, b) ((xcoff_backend (a)->_xcoff_stub_indirect_call_code[(b)]))
|
||||
#define bfd_xcoff_stub_indirect_call_size(a) ((xcoff_backend (a)->_xcoff_stub_indirect_call_size))
|
||||
#define bfd_xcoff_stub_shared_call_code(a, b) ((xcoff_backend (a)->_xcoff_stub_shared_call_code[(b)]))
|
||||
#define bfd_xcoff_stub_shared_call_size(a) ((xcoff_backend (a)->_xcoff_stub_shared_call_size))
|
||||
|
||||
/* Check for the magic number U803XTOCMAGIC or U64_TOCMAGIC for 64 bit
|
||||
targets. */
|
||||
#define bfd_xcoff_is_xcoff64(a) \
|
||||
@ -211,11 +225,12 @@ struct xcoff_backend_data_rec
|
||||
#define N_ONES(n) (((((bfd_vma) 1 << ((n) - 1)) - 1) << 1) | 1)
|
||||
|
||||
typedef bool xcoff_reloc_function (bfd *, asection *, bfd *,
|
||||
struct internal_reloc *,
|
||||
struct internal_syment *,
|
||||
struct reloc_howto_struct *,
|
||||
bfd_vma, bfd_vma,
|
||||
bfd_vma *, bfd_byte *);
|
||||
struct internal_reloc *,
|
||||
struct internal_syment *,
|
||||
struct reloc_howto_struct *,
|
||||
bfd_vma, bfd_vma,
|
||||
bfd_vma *, bfd_byte *,
|
||||
struct bfd_link_info *);
|
||||
|
||||
typedef bool xcoff_complain_function (bfd *, bfd_vma, bfd_vma,
|
||||
struct reloc_howto_struct *);
|
||||
@ -261,4 +276,42 @@ struct xcoff_dwsect_name {
|
||||
extern const struct xcoff_dwsect_name
|
||||
xcoff_dwsect_names[XCOFF_DWSECT_NBR_NAMES];
|
||||
|
||||
/* Structure and functions needed by backend in order to handle
|
||||
stubs created in xcofflink.c. */
|
||||
|
||||
enum xcoff_stub_type
|
||||
{
|
||||
xcoff_stub_none,
|
||||
xcoff_stub_indirect_call,
|
||||
xcoff_stub_shared_call
|
||||
};
|
||||
|
||||
struct xcoff_stub_hash_entry
|
||||
{
|
||||
/* Base hash table entry structure. */
|
||||
struct bfd_hash_entry root;
|
||||
|
||||
enum xcoff_stub_type stub_type;
|
||||
|
||||
/* The hash table entry of the stub's csect. */
|
||||
struct xcoff_link_hash_entry *hcsect;
|
||||
|
||||
/* Offset in the stub's csect. */
|
||||
bfd_vma stub_offset;
|
||||
|
||||
/* The target's section. */
|
||||
asection *target_section;
|
||||
|
||||
/* The target's hash table entry. */
|
||||
struct xcoff_link_hash_entry *htarget;
|
||||
};
|
||||
|
||||
|
||||
extern enum xcoff_stub_type bfd_xcoff_type_of_stub
|
||||
(asection *, const struct internal_reloc *, bfd_vma,
|
||||
struct xcoff_link_hash_entry *);
|
||||
|
||||
extern struct xcoff_stub_hash_entry *bfd_xcoff_get_stub_entry
|
||||
(asection *, struct xcoff_link_hash_entry *, struct bfd_link_info *);
|
||||
|
||||
#endif /* LIBXCOFF_H */
|
||||
|
940
bfd/xcofflink.c
940
bfd/xcofflink.c
File diff suppressed because it is too large
Load Diff
@ -18,6 +18,17 @@
|
||||
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
|
||||
MA 02110-1301, USA. */
|
||||
|
||||
/* Used to pass info between ld and bfd. */
|
||||
struct bfd_xcoff_link_params
|
||||
{
|
||||
/* Linker stub bfd. */
|
||||
bfd *stub_bfd;
|
||||
|
||||
/* Linker call-backs. */
|
||||
asection * (*add_stub_section) (const char *, asection *);
|
||||
void (*layout_sections_again) (void);
|
||||
};
|
||||
|
||||
extern bool bfd_xcoff_split_import_path
|
||||
(bfd *, const char *, const char **, const char **);
|
||||
extern bool bfd_xcoff_set_archive_import_path
|
||||
@ -41,3 +52,9 @@ extern bool bfd_xcoff_build_dynamic_sections
|
||||
(bfd *, struct bfd_link_info *);
|
||||
extern bool bfd_xcoff_link_generate_rtinit
|
||||
(bfd *, const char *, const char *, bool);
|
||||
extern bool bfd_xcoff_link_init
|
||||
(struct bfd_link_info *, struct bfd_xcoff_link_params *);
|
||||
extern bool bfd_xcoff_size_stubs
|
||||
(struct bfd_link_info *info);
|
||||
extern bool bfd_xcoff_build_stubs
|
||||
(struct bfd_link_info *info);
|
||||
|
11
ld/ChangeLog
11
ld/ChangeLog
@ -1,3 +1,14 @@
|
||||
2022-04-20 Clément Chigot <clement.chigot@atos.net>
|
||||
|
||||
* emultempl/aix.em (params): New variable.
|
||||
(stub_file): New variable.
|
||||
(xcoff_add_stub_section): New function.
|
||||
(xcoff_layout_sections_again): New function
|
||||
(hook_in_stub): New function.
|
||||
(_after_allocation): Add stub creation.
|
||||
(_create_output_section_statements): Allocate stub file and
|
||||
pass params to backend.
|
||||
|
||||
2022-04-20 Clément Chigot <clement.chigot@atos.net>
|
||||
|
||||
* emultempl/aix.em (_after_allocation): New function.
|
||||
|
@ -63,6 +63,15 @@ static void gld${EMULATION_NAME}_free (void *);
|
||||
static void gld${EMULATION_NAME}_find_relocs (lang_statement_union_type *);
|
||||
static void gld${EMULATION_NAME}_find_exp_assignment (etree_type *);
|
||||
|
||||
static asection *xcoff_add_stub_section (const char *, asection *);
|
||||
static void xcoff_layout_sections_again (void);
|
||||
|
||||
static struct bfd_xcoff_link_params params = {
|
||||
NULL,
|
||||
&xcoff_add_stub_section,
|
||||
&xcoff_layout_sections_again
|
||||
};
|
||||
|
||||
|
||||
/* The file alignment required for each section. */
|
||||
static unsigned long file_align;
|
||||
@ -138,6 +147,9 @@ static int rtld;
|
||||
/* Explicit command line library path, -blibpath */
|
||||
static char *command_line_blibpath = NULL;
|
||||
|
||||
/* Fake input file for stubs. */
|
||||
static lang_input_statement_type *stub_file;
|
||||
|
||||
/* This routine is called before anything else is done. */
|
||||
|
||||
static void
|
||||
@ -154,6 +166,7 @@ gld${EMULATION_NAME}_before_parse (void)
|
||||
|
||||
link_info.init_function = NULL;
|
||||
link_info.fini_function = NULL;
|
||||
|
||||
}
|
||||
|
||||
/* Handle AIX specific options. */
|
||||
@ -1009,12 +1022,157 @@ gld${EMULATION_NAME}_before_allocation (void)
|
||||
before_allocation_default ();
|
||||
}
|
||||
|
||||
struct hook_stub_info
|
||||
{
|
||||
lang_statement_list_type add;
|
||||
asection *input_section;
|
||||
};
|
||||
|
||||
/* Traverse the linker tree to find the spot where the stub goes. */
|
||||
|
||||
static bool
|
||||
hook_in_stub (struct hook_stub_info *info, lang_statement_union_type **lp)
|
||||
{
|
||||
lang_statement_union_type *l;
|
||||
bool ret;
|
||||
|
||||
for (; (l = *lp) != NULL; lp = &l->header.next)
|
||||
{
|
||||
switch (l->header.type)
|
||||
{
|
||||
case lang_constructors_statement_enum:
|
||||
ret = hook_in_stub (info, &constructor_list.head);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case lang_output_section_statement_enum:
|
||||
ret = hook_in_stub (info,
|
||||
&l->output_section_statement.children.head);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case lang_wild_statement_enum:
|
||||
ret = hook_in_stub (info, &l->wild_statement.children.head);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case lang_group_statement_enum:
|
||||
ret = hook_in_stub (info, &l->group_statement.children.head);
|
||||
if (ret)
|
||||
return ret;
|
||||
break;
|
||||
|
||||
case lang_input_section_enum:
|
||||
if (l->input_section.section == info->input_section)
|
||||
{
|
||||
/* We've found our section. Insert the stub immediately
|
||||
after its associated input section. */
|
||||
*(info->add.tail) = l->header.next;
|
||||
l->header.next = info->add.head;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case lang_data_statement_enum:
|
||||
case lang_reloc_statement_enum:
|
||||
case lang_object_symbols_statement_enum:
|
||||
case lang_output_statement_enum:
|
||||
case lang_target_statement_enum:
|
||||
case lang_input_statement_enum:
|
||||
case lang_assignment_statement_enum:
|
||||
case lang_padding_statement_enum:
|
||||
case lang_address_statement_enum:
|
||||
case lang_fill_statement_enum:
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Call-back for bfd_xcoff_link_relocations.
|
||||
Create a new stub section, and arrange for it to be linked
|
||||
immediately before INPUT_SECTION. */
|
||||
|
||||
static asection *
|
||||
xcoff_add_stub_section (const char *stub_sec_name, asection *input_section)
|
||||
{
|
||||
asection *stub_sec;
|
||||
flagword flags;
|
||||
asection *output_section;
|
||||
lang_output_section_statement_type *os;
|
||||
struct hook_stub_info info;
|
||||
|
||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE
|
||||
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_KEEP);
|
||||
stub_sec = bfd_make_section_anyway_with_flags (stub_file->the_bfd,
|
||||
stub_sec_name, flags);
|
||||
if (stub_sec == NULL)
|
||||
goto err_ret;
|
||||
|
||||
output_section = input_section->output_section;
|
||||
os = lang_output_section_get (output_section);
|
||||
|
||||
info.input_section = input_section;
|
||||
lang_list_init (&info.add);
|
||||
lang_add_section (&info.add, stub_sec, NULL, NULL, os);
|
||||
|
||||
if (info.add.head == NULL)
|
||||
goto err_ret;
|
||||
|
||||
if (hook_in_stub (&info, &os->children.head))
|
||||
return stub_sec;
|
||||
|
||||
err_ret:
|
||||
einfo (_("%X%P: can not make stub section: %E\n"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Another call-back for bfd_xcoff_link_relocations. */
|
||||
|
||||
static void
|
||||
xcoff_layout_sections_again (void)
|
||||
{
|
||||
/* If we have changed sizes of the stub sections, then we need
|
||||
to recalculate all the section offsets. This may mean we need to
|
||||
add even more stubs. */
|
||||
lang_relax_sections (true);
|
||||
}
|
||||
|
||||
/* Call the back-end to verify relocations. */
|
||||
|
||||
static void
|
||||
gld${EMULATION_NAME}_after_allocation (void)
|
||||
{
|
||||
|
||||
/* If generating a relocatable output file, then we don't have any
|
||||
stubs. */
|
||||
if (stub_file != NULL && !bfd_link_relocatable (&link_info))
|
||||
{
|
||||
/* Call into the BFD backend to do the real work. */
|
||||
if (!bfd_xcoff_size_stubs (&link_info))
|
||||
einfo (_("%X%P: can not size stub sections: %E\n"));
|
||||
}
|
||||
|
||||
/* Now that everything is in place, finalize the dynamic sections. */
|
||||
if (!bfd_xcoff_build_dynamic_sections (link_info.output_bfd, &link_info))
|
||||
einfo (_("%F%P: failed to layout dynamic sections: %E\n"));
|
||||
|
||||
if (!bfd_link_relocatable (&link_info))
|
||||
{
|
||||
/* Now build the linker stubs. */
|
||||
if (stub_file != NULL && stub_file->the_bfd->sections != NULL)
|
||||
{
|
||||
if (! bfd_xcoff_build_stubs (&link_info))
|
||||
einfo (_("%X%P: can not build stubs: %E\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static char *
|
||||
@ -1503,11 +1661,35 @@ fragment <<EOF
|
||||
static void
|
||||
gld${EMULATION_NAME}_create_output_section_statements (void)
|
||||
{
|
||||
if ((bfd_get_flavour (link_info.output_bfd) != bfd_target_xcoff_flavour))
|
||||
return;
|
||||
|
||||
/* Stub file */
|
||||
stub_file = lang_add_input_file ("linker stubs",
|
||||
lang_input_file_is_fake_enum,
|
||||
NULL);
|
||||
stub_file->the_bfd = bfd_create ("linker stubs", link_info.output_bfd);
|
||||
if (stub_file->the_bfd == NULL
|
||||
|| !bfd_set_arch_mach (stub_file->the_bfd,
|
||||
bfd_get_arch (link_info.output_bfd),
|
||||
bfd_get_mach (link_info.output_bfd)))
|
||||
{
|
||||
einfo (_("%F%P: can not create stub BFD: %E\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
stub_file->the_bfd->flags |= BFD_LINKER_CREATED;
|
||||
ldlang_add_file (stub_file);
|
||||
params.stub_bfd = stub_file->the_bfd;
|
||||
|
||||
/* Pass linker params to the back-end. */
|
||||
if (!bfd_xcoff_link_init (&link_info, ¶ms))
|
||||
einfo (_("%F%P: can not init BFD: %E\n"));
|
||||
|
||||
/* __rtinit */
|
||||
if ((bfd_get_flavour (link_info.output_bfd) == bfd_target_xcoff_flavour)
|
||||
&& (link_info.init_function != NULL
|
||||
|| link_info.fini_function != NULL
|
||||
|| rtld))
|
||||
if (link_info.init_function != NULL
|
||||
|| link_info.fini_function != NULL
|
||||
|| rtld)
|
||||
{
|
||||
initfini_file = lang_add_input_file ("initfini",
|
||||
lang_input_file_is_file_enum,
|
||||
|
Reference in New Issue
Block a user