Reputation: 493
So I know that we can add a custom section to an ELF file and have functions and structures enforced to be mapped in to custom sections.
This can be done by __atribute__ section("sectionname")
Here is a readelf output from my current ELF that has a custom section names .my_custom_section
that contains a structure named ver_info
Structure:
typedef struct version_info
{
int dd ;
int mm;
int yy;
int hr;
int min;
char *software_type;
char *software_version;
char *hex_tools_version;
} version_info;
version_info ver_info __attribute__ ((section(".my_custom_section"))) = {7, 10, 2013, 17, 17, "some_type", "some_sw_version", "some_version"} ;
Here is how the elf read looks like:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .hash HASH 000000d4 0000d4 00003c 04 A 2 0 4
[ 2] .dynsym DYNSYM 00000110 000110 0000a0 10 A 3 5 4
[ 3] .dynstr STRTAB 000001b0 0001b0 000026 00 A 0 0 1
[ 4] .rela.dyn RELA 000001d8 0001d8 000024 0c A 2 0 4
[ 5] .plt PROGBITS 00001000 001000 000000 00 AX 0 0 16
[ 6] .text PROGBITS 00001000 001000 00001c 00 AX 0 0 4
[ 7] .rodata PROGBITS 00002000 002000 000027 00 A 0 0 1
[ 8] .dynamic DYNAMIC 00004000 003000 000078 08 WA 3 0 4
[ 9] .got PROGBITS 00004078 003078 000000 00 WA 0 0 4
[10] .got.plt PROGBITS 00004078 003078 000010 04 WA 0 0 8
[11] .my_custom_sectio PROGBITS 00004088 003088 000020 00 WA 0 0 4
[12] .bss NOBITS 000040c0 0030a8 000000 00 WA 0 0 1
[13] .comment PROGBITS 00000000 0030a8 000028 01 MS 0 0 1
[14] .shstrtab STRTAB 00000000 0030d0 000081 00 0 0 1
[15] .symtab SYMTAB 00000000 0033fc 000180 10 16 19 4
[16] .strtab STRTAB 00000000 00357c 000075 00 0 0 1
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00000000 0x00000000 0x001fc 0x001fc R 0x1000
LOAD 0x001000 0x00001000 0x00001000 0x0001c 0x0001c R E 0x1000
LOAD 0x002000 0x00002000 0x00002000 0x00027 0x00027 R 0x1000
LOAD 0x003000 0x00004000 0x00004000 0x000a8 0x000c0 RW 0x1000
DYNAMIC 0x003000 0x00004000 0x00004000 0x00078 0x00078 RW 0x4
Section to Segment mapping:
Segment Sections...
00 .hash .dynsym .dynstr .rela.dyn
01 .text
02 .rodata
03 .dynamic .got.plt .my_custom_section
04 .dynamic
In this case my custom section is getting clubbed with .dynamic
, .got.plt
sections and mapped to segment 03. I want to map this section as a independent segment itself.
Can we have a control over mapping a section to a segment? How would you go about it?
EDIT:
1. Why not dlsym
for this structure symbol: The reason I am not so keen on adding this structure as a dynamic symbol is that I am writing an API to read the Version Information (which I plan to have contained in a separate segment), which will ultimately determine if I should dlopen
this SO file at all. It is a part of security measure to avoid opening an outdated SO.
2.Use of custom linker script: I am now using a custom linker script that adds the following section:
.my_custom_section() :
{
KEEP (*version_info.o (.rodata* ))
}
This does let me to create a section of desired name and place my data into it. But I am still struggling to avoid this section getting clubbed with .rodata
or some other sections.
I am sure that by specifying some configuration in linker script would allow me to map this section as an independent segment but that is exactly what I am trying to figure out.
Upvotes: 3
Views: 3525
Reputation: 2373
It might be already irrelevant for you, but it is PHDRS
command you were looking for. Here is an example (slightly modified) from Using LD, the GNU linker - PHDRS
PHDRS
{
headers PT_PHDR PHDRS ;
interp PT_INTERP ;
text PT_LOAD FILEHDR PHDRS ;
data PT_LOAD ;
dynamic PT_DYNAMIC ;
}
SECTIONS
{
. = SIZEOF_HEADERS;
.interp : { *(.interp) } :text :interp
.text : { *(.text) } :text
.rodata : { *(.rodata) } :text /* explicitly put in :text */
...
. = . + 0x1000; /* move to a new page in memory */
.data : { *(.data) } :data
.dynamic : { *(.dynamic) } :data :dynamic
...
}
Here you have 5 segments: headers, interp, text, data, dynamic
.
Look at rodata
section explicitly placed into text
segment
Upvotes: 0
Reputation: 2696
That this is an instruction that you have to give to the linker. Exactly how you do this depends on which linker you're using.
With GNU ld, the "right" way is to use a custom linker script, which you can provide using the -T
option. You can see the default linker script by typing ld --verbose
. It's a similar story for other linkers: the BSD linker (as used by Mac OSX), uses an order file (specified with -order_file
), the Solaris linker uses a map file (specified with -M
), and so on. They all do pretty much the same thing.
Note that each platform and each CPU family generally has its own link specification, so a GNU ld linker script that works on x86_64 targets may not work on ARM, even if they are both Linux. It's a similar story for the BSD family. Generally speaking, you should get your platform's linker script and amend it as needed. You should probably only write your own linker script from scratch if this is for a custom platform (e.g. it's firmware, you're writing your own OS, or what have you).
If this is code that needs to be cross-platform, then there are no good solutions. There are some "wrong" ways to do it which could work, such as hacking with objcopy
, but I don't recommend them.
Having said that, you should probably ask yourself if this is really what you want. If what you need is data which some custom tool or framework (e.g. a dynamic link loader) can find easily, can't you use dlsym
or the equivalent?
EDIT: It's 7 years later, and I just noticed that there is more information. I hope this isn't too late!
GNU ld has two additional commands in its linker scripts that you may not be aware of: PHDRS and SECTIONS. I've never used them, but they do what you want.
Upvotes: 3