This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
BFD how to create relocation entries?
- From: Josef Eisl <zapster at zapster dot cc>
- To: binutils at sourceware dot org
- Date: Thu, 01 Aug 2013 11:36:44 +0200
- Subject: BFD how to create relocation entries?
Hi!
I have a question regarding relocations in the BFD library. Creating
sections and symbols is straight forward (great documentation on these
topics, btw!) but adding relocation entries seems to be harder/not that
well documented.
I've written a minimal example to demonstrate the problem. It is
targeting x86_64 and elf by I guess my issues are not completely target
dependent. In my example (source code is attached) I create a .text section
mov 0x0(rip), %xmm0
retq
and a .rodata section as well as symbol (foo) pointing to .text.
What I want to do is adding a relocation entry stating that the rip
offset (.text offset 4, 32bit) should be replaced by the relative
address of the final position of the .rodata segment (offset 0).
If my understanding of the doc is correct the howto structure is used to
encode the sort of relocation I want to be performed so the following
piece should do it in my case, right?
reloc_howto_type* howto = bfd_reloc_type_lookup(abfd, BFD_RELOC_32_PCREL);
The next thing is setting up arecent. What are the correct values?
address, addend and howto are more or less clear but what about
sym_ptr_ptr? To my understanding this should be the pointer to the
pointer of the foo symbol in the symbol table. Can I use the table
(entry) used for bfd_set_symtab or do I have to create a new table (e.g.
with bfd_canonicalize_symtbl())?
According to the docs I have to install the relocation using
bfd_install_relocation(). I've seen many discussions on that function
and what it is supposed to do. Again, I'm confused by the parameters.
What is data supposed to point to? I would interpret data_start as the
offset of the data in the data section (0 in the example case). Is
input_section the source of the relocation target, e.g. the .rodata section?
Is there still more to be done beside bfd_close(abfd) to get the
relocation entry into the output file?
Any hints are highly appreciated. Many thanks in advance for sharing
your insights,
Josef
#include <bfd.h>
unsigned long data[] = {
0x400921fb54442d18 /* pi */
};
const unsigned datalen = 8;
unsigned char code[] = {
0xf3, 0x0f, 0x7e, 0x05 ,0x00, 0x00, 0x00, 0x00, /* movq 0x0(%rip),%xmm0 */
0xc3 /* retq */
};
const unsigned codelen = 9;
int main(int argc, char* argv[]) {
const char* bfd_arch = "i386:x86-64";
const char* bfd_target = "elf64-x86-64";
const bfd_arch_info_type *arch_info;
bfd *abfd;
asection *data_section;
asection *code_section;
asymbol *new_smbl;
asymbol *ptrs[2];
reloc_howto_type* howto;
arelent reloc_entry;
char *err;
/* open file */
abfd = bfd_openw("foo.o",bfd_target);
/* set architecture */
arch_info = bfd_scan_arch(bfd_arch);
bfd_set_arch_info(abfd,arch_info);
/* set format */
bfd_set_format(abfd, bfd_object);
/* create data_section */
data_section = bfd_make_section_anyway_with_flags(abfd, ".rodata",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_DATA );
/* set data_section size */
bfd_set_section_size(abfd, data_section, datalen);
/* set alignment */
data_section->alignment_power = 2;
/* create code_section */
code_section = bfd_make_section_anyway_with_flags(abfd, ".text",
SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_READONLY | SEC_CODE );
/* set code_section size */
bfd_set_section_size(abfd, code_section, codelen);
/* set alignment */
code_section->alignment_power = 2;
/* create symbol */
new_smbl = bfd_make_empty_symbol(abfd);
new_smbl->name = "foo";
new_smbl->section = code_section;
new_smbl->flags = BSF_GLOBAL;
/* symbol list */
ptrs[0] = new_smbl;
ptrs[1] = 0;
/* insert symbol list */
bfd_set_symtab(abfd, ptrs, 1);
/* XXX create relocation entries */
/* set contents */
/* this starts writing so do it at the end */
bfd_set_section_contents(abfd,data_section, data, 0,datalen);
bfd_set_section_contents(abfd,code_section, code, 0,codelen);
/* close file */
bfd_close(abfd);
return 0;
}