These are notes on the bfd API, see more:
The very top-level of GNU Linker source code
ld/ldmain.c
main()
- lang_process()
- ldwrite()
ld/ldlang.c
lang_process()
- lang_check_relocs
- bfd_link_check_relocs - Phase 1, book keeping
- ldemul_before_allocation - Phase 2, creating space
- ldemul_after_allocation
ld/ldwrite.c
ldwrite()
- bfd_final_link - Phase 3 and 4, relocate_section and finish
ld/emultempl/elf.em - generates ldemul_* apis - backed by elf bfd backend
ldemul_before_allocation()
- ldelf_before_allocation()
- ldelf_after_allocation()
ld/ldelf.c
ldelf_before_allocation()
- bfd_elf_size_dynamic_sections
Implementations of BFD apis
bfd/linker.c - top level
- bfd_link_check_relocs - calls BFD_SEND (abfd, _bfd_link_check_relocs, (abfd, info)
bfd/elflink.c - Calls into elf implementations
- _bfd_elf_link_check_relocs
bfd/elf32-or1k.c - elf implementation for openrisc
or1k_elf_check_relocs - BFD API, P1 validate reloc, init .rela sections, .got sections
bfd_elf_size_dynamic_sections
- or1k_elf_size_dynamic_sections - BFD API, P2 calculate section sizes
- allocate_dynrelocs - sreloc (finally alloc space)
bfd/elflink.c - These 4 functions all call into _bfd_elf_link_create_dynamic_sections()
bfd_elf_link_add_symbols
elf_link_add_object_symbols
elf_add_dt_needed_tag
elf_link_add_object_symbols
_bfd_elf_link_create_dynamic_sections
- _bfd_elf_create_dynamic_sections
bfd/elflink.c
_bfd_elf_create_dynamic_sections - BFD API, P2 generic code to create sections, .plt, .rela.bss etc
bfd/elflink.c
bfd_elf_gc_common_final_link
- bfd_elf_gc_common_finalize_got_offsets - local_got.offsets setup
bfd_elf_final_link()
- elf_link_input_bfd
- or1k_elf_relocate_section - BFD API, P3 main worker writes to sections
- travers(elf_link_output_extsym) - called 2 times
- or1k_elf_finish_dynamic_symbol - BFD API, P4 for a symbol write to .plt, .got + .got.rela
- or1k_elf_finish_dynamic_sections - BFD API, P4 add final things to .plt, etc
$ grep 'elf_link_input_bfd\|elf_link_output_extsym\|finish_dynamic_sections' bfd/elflink.c
elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
elf_link_input_bfd (struct elf_final_link_info *flinfo, bfd *input_bfd)
if (! elf_link_input_bfd (&flinfo, sub))
bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
if (! (*bed->elf_backend_finish_dynamic_sections) (abfd, info))
Function Docs
Phase 1 - book keeping (check_relocs)
The or1k_elf_check_relocs
function is called during the first phase to
validate relocations, returns FALSE if there are issues. It also does
some book keeping.
- abfd - The current elf object file we are working on
- sec - The current elf section we are working on
- info - the bfd API
- relocs - The relocations from the current section
static bfd_boolean
or1k_elf_check_relocs (bfd *abfd,
struct bfd_link_info *info,
asection *sec,
const Elf_Internal_Rela *relocs)
#define elf_backend_check_relocs or1k_elf_check_relocs
Phase 2 - creating space (size_dynamic_sections + _bfd_elf_create_dynamic_sections)
The or1k_elf_size_dynamic_sections
function iterates over all object
files to calculate the size of stuff, it uses:
- info - the API to bfd provides access to everything, this function uses:
or1k_elf_hash_table (info)
- calledhtab
a reference toelf_link_hash_table
which has sections.htab->root.splt
- the plt sectionhtab->root.sgot
- the got sectionhtab->root.srelgot
- the relgot section (relocations against the got)htab->root.sgotplt
- the gotplt sectionhtab->root.dynobj
- a special bfd to which sections are created (created inor1k_elf_check_relocs
)root.dynamic_sections_created
- true if sections like.interp
have been created by the linkerinfo->input_bfds
- loop over all bfds (elf objects)
Settig up the sizes of the .got
section (global offset table) and .plt
section (procedure link table) is done by iterating through all symbols with the allocate_dynrelocs
interator.
Sub function of or1k_elf_size_dynamic_sections
allocate_dynrelocs
is used to additionaly set size of .gotplt
which sometime later gets combinted with the .got
somehow. The allocate_dynrelocs
is a visitor function that is used when
iterating over each elf_link_hash_entry
which represents a symbol.
pseudocode
allocate_dynrelocs(h) {
if (h->plt.refcount > 0) {
.gotplt->size ++;
.relocations->size ++;
}
if (h->got.refcount > 0) {
.got->size ++;
.relocations->size ++;
}
do something with h->dyn_relocs which I don't understand
but in the end it doe sreloc->size ++
}
The sub function of allocate_dynrelocs
or1k_set_got_and_rela_sizes
is used to increment .got
and .rela
section sizes per tls symbols.
static bfd_boolean
or1k_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
struct bfd_link_info *info)
#define elf_backend_size_dynamic_sections or1k_elf_size_dynamic_sections
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
Phase 3 - linking (relocate_section)
For each input section in an input bfd (.o
file) figure out where they will exist in the output bfd.
Fill in relocation placeholders in .text
sections. Fill out data in .got
and .rela
sections.
static bfd_boolean
or1k_elf_relocate_section (bfd *output_bfd,
struct bfd_link_info *info,
bfd *input_bfd,
asection *input_section,
bfd_byte *contents,
Elf_Internal_Rela *relocs,
Elf_Internal_Sym *local_syms,
asection **local_sections)
#define elf_backend_relocate_section or1k_elf_relocate_section
Phase 4 - finishing up (finish_dynamic_symbol + finish_dynamic_sections)
Write to .plt
static bfd_boolean
or1k_elf_finish_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
static bfd_boolean
or1k_elf_finish_dynamic_symbol (bfd *output_bfd,
struct bfd_link_info *info,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
#define elf_backend_finish_dynamic_sections or1k_elf_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol or1k_elf_finish_dynamic_symbol
Insane things inbetween
These are important but I cant see why they need to be specific to openrisc or anyone writing a new port.
#define elf_backend_copy_indirect_symbol or1k_elf_copy_indirect_symbol
#define elf_backend_adjust_dynamic_symbol or1k_elf_adjust_dynamic_symbol
There is a whole article on this now How TLS Works ...