3
* This is a program that removes unreferenced strings from the .dynstr
4
* section in ELF shared objects. It also shrinks the .dynstr section and
5
* relocates all symbols after it.
7
* This program was written and copyrighted by:
8
* Alexander Larsson <alla@lysator.liu.se>
12
* This Source Code Form is subject to the terms of the Mozilla Public
13
* License, v. 2.0. If a copy of the MPL was not distributed with this
14
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
20
#include <sys/types.h>
29
Elf32_Ehdr *elf_header = NULL;
30
#define FILE_OFFSET(offset) ((unsigned char *)(elf_header) + (offset))
32
struct dynamic_symbol {
38
GHashTable *used_dynamic_symbols = NULL;
39
/* Data is dynamic_symbols, hashes on old_index */
40
Elf32_Word hole_index;
44
Elf32_Addr hole_addr_start;
45
Elf32_Addr hole_addr_remap_start;
46
Elf32_Addr hole_addr_remap_end;
50
unsigned char machine_type;
53
read_word(Elf32_Word w)
56
w = GUINT32_SWAP_LE_BE(w);
61
read_sword(Elf32_Sword w)
64
w = (Elf32_Sword)GUINT32_SWAP_LE_BE((guint32)w);
69
write_word(Elf32_Word *ptr, Elf32_Word w)
72
w = GUINT32_SWAP_LE_BE(w);
77
read_half(Elf32_Half h)
80
h = GUINT16_SWAP_LE_BE(h);
85
write_half(Elf32_Half *ptr, Elf32_Half h)
88
h = GUINT16_SWAP_LE_BE(h);
93
setup_byteswapping(unsigned char ei_data)
96
#if G_BYTE_ORDER == G_BIG_ENDIAN
97
if (ei_data == ELFDATA2LSB)
100
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
101
if (ei_data == ELFDATA2MSB)
108
elf_find_section_num(int section_index)
111
Elf32_Word sectionsize;
113
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
114
sectionsize = read_half(elf_header->e_shentsize);
116
section = (Elf32_Shdr *)((char *)section + sectionsize*section_index);
122
elf_find_section_named(char *name)
125
Elf32_Shdr *strtab_section;
126
Elf32_Word sectionsize;
131
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
133
strtab_section = elf_find_section_num(read_half(elf_header->e_shstrndx));
135
strtab = (char *)FILE_OFFSET(read_word(strtab_section->sh_offset));
137
sectionsize = read_half(elf_header->e_shentsize);
138
numsections = read_half(elf_header->e_shnum);
140
for (i=0;i<numsections;i++) {
141
if (strcmp(&strtab[read_word(section->sh_name)], name) == 0) {
144
section = (Elf32_Shdr *)((char *)section + sectionsize);
151
elf_find_section(Elf32_Word sh_type)
154
Elf32_Word sectionsize;
158
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
159
sectionsize = read_half(elf_header->e_shentsize);
160
numsections = read_half(elf_header->e_shnum);
162
for (i=0;i<numsections;i++) {
163
if (read_word(section->sh_type) == sh_type) {
166
section = (Elf32_Shdr *)((char *)section + sectionsize);
172
elf_find_next_higher_section(Elf32_Word offset)
176
Elf32_Word sectionsize;
180
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
181
sectionsize = read_half(elf_header->e_shentsize);
182
numsections = read_half(elf_header->e_shnum);
186
for (i=0;i<numsections;i++) {
187
if (read_word(section->sh_offset) >= offset) {
188
if (higher == NULL) {
190
} else if (read_word(section->sh_offset) < read_word(higher->sh_offset)) {
195
section = (Elf32_Shdr *)((char *)section + sectionsize);
202
vma_to_offset(Elf32_Addr addr)
206
Elf32_Word sectionsize;
210
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
211
sectionsize = read_half(elf_header->e_shentsize);
212
numsections = read_half(elf_header->e_shnum);
216
for (i=0;i<numsections;i++) {
217
if ( (addr >= read_word(section->sh_addr)) &&
218
(addr < read_word(section->sh_addr) + read_word(section->sh_size)) ) {
219
return read_word(section->sh_offset) + (addr - read_word(section->sh_addr));
222
section = (Elf32_Shdr *)((char *)section + sectionsize);
225
fprintf(stderr, "Warning, unable to convert address %d (0x%x) to file offset\n",
232
find_segment_addr_min_max(Elf32_Word file_offset,
233
Elf32_Addr *start, Elf32_Addr *end)
236
Elf32_Word segmentsize;
240
segment = (Elf32_Phdr *)FILE_OFFSET(read_word(elf_header->e_phoff));
241
segmentsize = read_half(elf_header->e_phentsize);
242
numsegments = read_half(elf_header->e_phnum);
244
for (i=0;i<numsegments;i++) {
245
if ((file_offset >= read_word(segment->p_offset)) &&
246
(file_offset < read_word(segment->p_offset) + read_word(segment->p_filesz))) {
247
*start = read_word(segment->p_vaddr);
248
*end = read_word(segment->p_vaddr) + read_word(segment->p_memsz);
252
segment = (Elf32_Phdr *)((char *)segment + segmentsize);
254
fprintf(stderr, "Error: Couldn't find segment in find_segment_addr_min_max()\n");
258
dynamic_find_tag(Elf32_Shdr *dynamic, Elf32_Sword d_tag)
263
element = (Elf32_Dyn *)FILE_OFFSET(read_word(dynamic->sh_offset));
264
for (i=0; read_sword(element[i].d_tag) != DT_NULL; i++) {
265
if (read_sword(element[i].d_tag) == d_tag) {
266
return FILE_OFFSET(read_word(element[i].d_un.d_ptr));
274
fixup_offset(Elf32_Word offset)
276
if (offset >= hole_index) {
277
return offset - hole_len;
283
fixup_size(Elf32_Word offset, Elf32_Word size)
285
/* Note: Doesn't handle the cases where the hole and the size intersect
288
if ( (hole_index >= offset) &&
289
(hole_index < offset + size)){
290
return size - hole_len;
297
fixup_addr(Elf32_Addr addr)
303
if ( (addr < hole_addr_remap_start) ||
304
(addr >= hole_addr_remap_end))
308
if (addr >= hole_addr_start) {
309
return addr - hole_len;
315
fixup_addr_size(Elf32_Addr addr, Elf32_Word size)
317
/* Note: Doesn't handle the cases where the hole and the size intersect
320
if ( (addr < hole_addr_remap_start) ||
321
(addr >= hole_addr_remap_end))
324
if ( (hole_addr_start >= addr) &&
325
(hole_addr_start < addr + size)){
326
return size - hole_len;
333
possibly_add_string(int name_idx, const char *name)
335
struct dynamic_symbol *dynamic_symbol;
337
dynamic_symbol = g_hash_table_lookup(used_dynamic_symbols, (gpointer) name_idx);
339
if (dynamic_symbol == NULL) {
341
dynamic_symbol = g_new(struct dynamic_symbol, 1);
343
dynamic_symbol->old_index = name_idx;
344
dynamic_symbol->new_index = 0;
345
dynamic_symbol->string = g_strdup(name);
347
g_hash_table_insert(used_dynamic_symbols, (gpointer)name_idx, dynamic_symbol);
348
/*printf("added dynamic string: %s (%d)\n", dynamic_symbol->string, name_idx);*/
354
fixup_string(Elf32_Word old_idx)
356
struct dynamic_symbol *dynamic_symbol;
361
dynamic_symbol = g_hash_table_lookup(used_dynamic_symbols, (gpointer) old_idx);
363
if (dynamic_symbol == NULL) {
364
fprintf(stderr, "AAAAAAAAAAAARGH!? Unknown string found in fixup (index: %d)!\n", old_idx);
368
return dynamic_symbol->new_index;
374
add_strings_from_dynsym(Elf32_Shdr *dynsym, char *strtab)
377
Elf32_Sym *symbol_end;
378
Elf32_Word entry_size;
381
symbol = (Elf32_Sym *)FILE_OFFSET(read_word(dynsym->sh_offset));
382
symbol_end = (Elf32_Sym *)FILE_OFFSET(read_word(dynsym->sh_offset) + read_word(dynsym->sh_size));
383
entry_size = read_word(dynsym->sh_entsize);
385
while (symbol < symbol_end) {
387
struct dynamic_symbol *dynamic_symbol;
389
name_idx = read_word(symbol->st_name);
390
possibly_add_string(name_idx, &strtab[name_idx]);
393
symbol = (Elf32_Sym *)((char *)symbol + entry_size);
399
fixup_strings_in_dynsym(Elf32_Shdr *dynsym)
402
Elf32_Sym *symbol_end;
403
Elf32_Word entry_size;
406
symbol = (Elf32_Sym *)FILE_OFFSET(read_word(dynsym->sh_offset));
407
symbol_end = (Elf32_Sym *)FILE_OFFSET(read_word(dynsym->sh_offset) + read_word(dynsym->sh_size));
408
entry_size = read_word(dynsym->sh_entsize);
410
while (symbol < symbol_end) {
411
struct dynamic_symbol *dynamic_symbol;
413
write_word(&symbol->st_name,
414
fixup_string(read_word(symbol->st_name)));
416
symbol = (Elf32_Sym *)((char *)symbol + entry_size);
422
add_strings_from_dynamic(Elf32_Shdr *dynamic, char *strtab)
427
Elf32_Word entry_size;
429
entry_size = read_word(dynamic->sh_entsize);
432
element = (Elf32_Dyn *)FILE_OFFSET(read_word(dynamic->sh_offset));
433
while (read_sword(element->d_tag) != DT_NULL) {
435
switch(read_sword(element->d_tag)) {
439
name_idx = read_word(element->d_un.d_val);
440
/*if (name_idx) printf("d_tag: %d\n", element->d_tag);*/
441
possibly_add_string(name_idx, &strtab[name_idx]);
445
/*printf("unhandled d_tag: %d (0x%x)\n", element->d_tag, element->d_tag);*/
448
element = (Elf32_Dyn *)((char *)element + entry_size);
454
fixup_strings_in_dynamic(Elf32_Shdr *dynamic)
459
Elf32_Word entry_size;
461
entry_size = read_word(dynamic->sh_entsize);
463
element = (Elf32_Dyn *)FILE_OFFSET(read_word(dynamic->sh_offset));
464
while (read_sword(element->d_tag) != DT_NULL) {
466
switch(read_sword(element->d_tag)) {
470
write_word(&element->d_un.d_val,
471
fixup_string(read_word(element->d_un.d_val)));
475
/*printf("unhandled d_tag: %d (0x%x)\n", element->d_tag, element->d_tag);*/
478
element = (Elf32_Dyn *)((char *)element + entry_size);
485
add_strings_from_ver_d(Elf32_Shdr *ver_d, char *strtab)
487
Elf32_Verdaux *veraux;
488
Elf32_Verdef *verdef;
494
verdef = (Elf32_Verdef *)FILE_OFFSET(read_word(ver_d->sh_offset));
497
num_aux = read_half(verdef->vd_cnt);
498
veraux = (Elf32_Verdaux *)((char *)verdef + read_word(verdef->vd_aux));
499
for (i=0; i<num_aux; i++) {
500
name_idx = read_word(veraux->vda_name);
501
possibly_add_string(name_idx, &strtab[name_idx]);
502
veraux = (Elf32_Verdaux *)((char *)veraux + read_word(veraux->vda_next));
505
cont = read_word(verdef->vd_next) != 0;
506
verdef = (Elf32_Verdef *)((char *)verdef + read_word(verdef->vd_next));
512
fixup_strings_in_ver_d(Elf32_Shdr *ver_d)
514
Elf32_Verdaux *veraux;
515
Elf32_Verdef *verdef;
521
verdef = (Elf32_Verdef *)FILE_OFFSET(read_word(ver_d->sh_offset));
524
num_aux = read_half(verdef->vd_cnt);
525
veraux = (Elf32_Verdaux *)((char *)verdef + read_word(verdef->vd_aux));
526
for (i=0; i<num_aux; i++) {
527
write_word(&veraux->vda_name,
528
fixup_string(read_word(veraux->vda_name)));
529
veraux = (Elf32_Verdaux *)((char *)veraux + read_word(veraux->vda_next));
532
cont = read_word(verdef->vd_next) != 0;
533
verdef = (Elf32_Verdef *)((char *)verdef + read_word(verdef->vd_next));
539
add_strings_from_ver_r(Elf32_Shdr *ver_r, char *strtab)
541
Elf32_Vernaux *veraux;
542
Elf32_Verneed *verneed;
548
verneed = (Elf32_Verneed *)FILE_OFFSET(read_word(ver_r->sh_offset));
551
name_idx = read_word(verneed->vn_file);
552
possibly_add_string(name_idx, &strtab[name_idx]);
553
num_aux = read_half(verneed->vn_cnt);
554
veraux = (Elf32_Vernaux *)((char *)verneed + read_word(verneed->vn_aux));
555
for (i=0; i<num_aux; i++) {
556
name_idx = read_word(veraux->vna_name);
557
possibly_add_string(name_idx, &strtab[name_idx]);
558
veraux = (Elf32_Vernaux *)((char *)veraux + read_word(veraux->vna_next));
561
cont = read_word(verneed->vn_next) != 0;
562
verneed = (Elf32_Verneed *)((char *)verneed + read_word(verneed->vn_next));
567
fixup_strings_in_ver_r(Elf32_Shdr *ver_r)
569
Elf32_Vernaux *veraux;
570
Elf32_Verneed *verneed;
576
verneed = (Elf32_Verneed *)FILE_OFFSET(read_word(ver_r->sh_offset));
579
write_word(&verneed->vn_file,
580
fixup_string(read_word(verneed->vn_file)));
581
num_aux = read_half(verneed->vn_cnt);
582
veraux = (Elf32_Vernaux *)((char *)verneed + read_word(verneed->vn_aux));
583
for (i=0; i<num_aux; i++) {
584
write_word(&veraux->vna_name,
585
fixup_string(read_word(veraux->vna_name)));
586
veraux = (Elf32_Vernaux *)((char *)veraux + read_word(veraux->vna_next));
589
cont = read_word(verneed->vn_next) != 0;
590
verneed = (Elf32_Verneed *)((char *)verneed + read_word(verneed->vn_next));
594
gboolean sum_size(gpointer key,
595
struct dynamic_symbol *sym,
598
*size += strlen(sym->string) + 1;
602
struct index_n_dynstr {
604
unsigned char *dynstr;
607
gboolean output_string(gpointer key,
608
struct dynamic_symbol *sym,
609
struct index_n_dynstr *x)
611
sym->new_index = x->index;
612
memcpy(x->dynstr + x->index, sym->string, strlen(sym->string) + 1);
613
x->index += strlen(sym->string) + 1;
619
generate_new_dynstr(Elf32_Word *size_out)
622
unsigned char *new_dynstr;
623
struct index_n_dynstr x;
625
size = 1; /* first a zero */
626
g_hash_table_foreach (used_dynamic_symbols,
631
new_dynstr = g_malloc(size);
635
x.dynstr = new_dynstr;
636
g_hash_table_foreach (used_dynamic_symbols,
637
(GHFunc)output_string,
648
Elf32_Word sectionsize;
652
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
653
sectionsize = read_half(elf_header->e_shentsize);
654
numsections = read_half(elf_header->e_shnum);
656
for (i=0;i<numsections;i++) {
657
write_word(§ion->sh_size,
658
fixup_size(read_word(section->sh_offset),
659
read_word(section->sh_size)));
660
write_word(§ion->sh_offset,
661
fixup_offset(read_word(section->sh_offset)));
662
write_word(§ion->sh_addr,
663
fixup_addr(read_word(section->sh_addr)));
665
section = (Elf32_Shdr *)((char *)section + sectionsize);
674
Elf32_Word segmentsize;
679
segment = (Elf32_Phdr *)FILE_OFFSET(read_word(elf_header->e_phoff));
680
segmentsize = read_half(elf_header->e_phentsize);
681
numsegments = read_half(elf_header->e_phnum);
683
for (i=0;i<numsegments;i++) {
684
write_word(&segment->p_filesz,
685
fixup_size(read_word(segment->p_offset),
686
read_word(segment->p_filesz)));
687
write_word(&segment->p_offset,
688
fixup_offset(read_word(segment->p_offset)));
690
write_word(&segment->p_memsz,
691
fixup_addr_size(read_word(segment->p_vaddr),
692
read_word(segment->p_memsz)));
693
write_word(&segment->p_vaddr,
694
fixup_addr(read_word(segment->p_vaddr)));
695
write_word(&segment->p_paddr,
696
read_word(segment->p_vaddr));
698
/* Consistancy checking: */
699
p_align = read_word(segment->p_align);
701
if ((read_word(segment->p_vaddr) - read_word(segment->p_offset))%p_align != 0) {
702
fprintf(stderr, "Warning, creating non-aligned segment addr: %x offset: %x allign: %x\n",
703
read_word(segment->p_vaddr), read_word(segment->p_offset), p_align);
707
segment = (Elf32_Phdr *)((char *)segment + segmentsize);
712
remap_elf_header(void)
714
write_word(&elf_header->e_phoff,
715
fixup_offset(read_word(elf_header->e_phoff)));
716
write_word(&elf_header->e_shoff,
717
fixup_offset(read_word(elf_header->e_shoff)));
719
write_word(&elf_header->e_entry,
720
fixup_addr(read_word(elf_header->e_entry)));
724
remap_symtab(Elf32_Shdr *symtab)
727
Elf32_Sym *symbol_end;
728
Elf32_Word entry_size;
730
symbol = (Elf32_Sym *)FILE_OFFSET(read_word(symtab->sh_offset));
731
symbol_end = (Elf32_Sym *)FILE_OFFSET(read_word(symtab->sh_offset) +
732
read_word(symtab->sh_size));
733
entry_size = read_word(symtab->sh_entsize);
735
while (symbol < symbol_end) {
736
write_word(&symbol->st_value,
737
fixup_addr(read_word(symbol->st_value)));
738
symbol = (Elf32_Sym *)((char *)symbol + entry_size);
743
/* Ugly global variables: */
744
Elf32_Addr got_data_start = 0;
745
Elf32_Addr got_data_end = 0;
749
remap_rel_section(Elf32_Rel *rel, Elf32_Word size, Elf32_Word entry_size)
756
rel_end = (Elf32_Rel *)((char *)rel + size);
758
while (rel < rel_end) {
759
type = ELF32_R_TYPE(read_word(rel->r_info));
760
switch (machine_type) {
762
if ((type == R_386_RELATIVE) || (type == R_386_JMP_SLOT)) {
763
/* We need to relocate the data this is pointing to too. */
764
offset = vma_to_offset(read_word(rel->r_offset));
766
addr = (Elf32_Addr *)FILE_OFFSET(offset);
768
fixup_addr(read_word(*addr)));
770
write_word(&rel->r_offset,
771
fixup_addr(read_word(rel->r_offset)));
774
/* The PPC always uses RELA relocations */
779
rel = (Elf32_Rel *)((char *)rel + entry_size);
784
remap_rela_section(Elf32_Rela *rela, Elf32_Word size, Elf32_Word entry_size)
786
Elf32_Rela *rela_end;
792
rela_end = (Elf32_Rela *)((char *)rela + size);
794
while (rela < rela_end) {
795
type = ELF32_R_TYPE(read_word(rela->r_info));
796
switch (machine_type) {
798
if ((type == R_386_RELATIVE) || (type == R_386_JMP_SLOT)) {
799
/* We need to relocate the data this is pointing to too. */
800
offset = vma_to_offset(read_word(rela->r_offset));
802
addr = (Elf32_Addr *)FILE_OFFSET(offset);
804
fixup_addr(read_word(*addr)));
806
write_word(&rela->r_offset,
807
fixup_addr(read_word(rela->r_offset)));
810
/* Some systems do not have PowerPC relocations defined */
814
write_word((Elf32_Word *)&rela->r_addend,
815
fixup_addr(read_word(rela->r_addend)));
816
/* Fall through for 32bit offset fixup */
820
write_word(&rela->r_offset,
821
fixup_addr(read_word(rela->r_offset)));
826
fprintf(stderr, "Warning, unhandled PPC relocation type %d\n", type);
832
rela = (Elf32_Rela *)((char *)rela + entry_size);
839
Elf32_Shdr *got_section;
842
Elf32_Word entry_size;
844
got_section = elf_find_section_named(".got");
845
if (got_section == NULL) {
846
fprintf(stderr, "Warning, no .got section\n");
850
got_data_start = read_word(got_section->sh_offset);
851
got_data_end = got_data_start + read_word(got_section->sh_size);
853
got = (Elf32_Addr *)FILE_OFFSET(got_data_start);
854
got_end = (Elf32_Addr *)FILE_OFFSET(got_data_end);
855
entry_size = read_word(got_section->sh_entsize);
858
fixup_addr(read_word(*got))); /* Pointer to .dynamic */
864
Elf32_Shdr *got_section;
867
Elf32_Word entry_size;
869
got_section = elf_find_section_named(".got");
870
if (got_section == NULL) {
871
fprintf(stderr, "Warning, no .got section\n");
875
got_data_start = read_word(got_section->sh_offset);
876
got_data_end = got_data_start + read_word(got_section->sh_size);
878
got = (Elf32_Addr *)FILE_OFFSET(got_data_start);
879
got_end = (Elf32_Addr *)FILE_OFFSET(got_data_end);
880
entry_size = read_word(got_section->sh_entsize);
882
/* Skip reserved part.
883
* Note that this should really be found by finding the
884
* _GLOBAL_OFFSET_TABLE symbol, as it could (according to
885
* the spec) point to the middle of the got.
887
got = (Elf32_Addr *)((char *)got + entry_size); /* Skip blrl instruction */
889
fixup_addr(read_word(*got))); /* Pointer to .dynamic */
894
get_dynamic_val(Elf32_Shdr *dynamic, Elf32_Sword tag)
897
Elf32_Word entry_size;
899
entry_size = read_word(dynamic->sh_entsize);
901
element = (Elf32_Dyn *)FILE_OFFSET(read_word(dynamic->sh_offset));
902
while (read_sword(element->d_tag) != DT_NULL) {
903
if (read_sword(element->d_tag) == tag) {
904
return read_word(element->d_un.d_val);
906
element = (Elf32_Dyn *)((char *)element + entry_size);
912
remap_dynamic(Elf32_Shdr *dynamic, Elf32_Word new_dynstr_size)
915
Elf32_Word entry_size;
917
Elf32_Word rel_entry_size;
921
Elf32_Word rel_start, rel_end, jmprel_start, jmprel_end;
923
entry_size = read_word(dynamic->sh_entsize);
925
/* Find out if REL/RELA and JMPREL overlaps: */
926
if (get_dynamic_val(dynamic, DT_PLTREL) == DT_REL) {
927
rel_start = get_dynamic_val(dynamic, DT_REL);
928
rel_end = rel_start + get_dynamic_val(dynamic, DT_RELSZ);
930
rel_start = get_dynamic_val(dynamic, DT_RELA);
931
rel_end = rel_start + get_dynamic_val(dynamic, DT_RELASZ);
933
jmprel_start = get_dynamic_val(dynamic, DT_JMPREL);
936
if ((jmprel_start >= rel_start) && (jmprel_start < rel_end))
939
element = (Elf32_Dyn *)FILE_OFFSET(read_word(dynamic->sh_offset));
940
while (read_sword(element->d_tag) != DT_NULL) {
941
switch(read_sword(element->d_tag)) {
943
write_word(&element->d_un.d_val, new_dynstr_size);
953
write_word(&element->d_un.d_ptr,
954
fixup_addr(read_word(element->d_un.d_ptr)));
957
rel_size = get_dynamic_val(dynamic, DT_PLTRELSZ);
958
if (!jmprel_overlaps) {
959
if (get_dynamic_val(dynamic, DT_PLTREL) == DT_REL) {
960
rel_entry_size = get_dynamic_val(dynamic, DT_RELENT);
961
rel = (Elf32_Rel *)FILE_OFFSET(vma_to_offset(read_word(element->d_un.d_ptr)));
962
remap_rel_section(rel, rel_size, rel_entry_size);
964
rel_entry_size = get_dynamic_val(dynamic, DT_RELAENT);
965
rela = (Elf32_Rela *)FILE_OFFSET(vma_to_offset(read_word(element->d_un.d_ptr)));
966
remap_rela_section(rela, rel_size, rel_entry_size);
969
write_word(&element->d_un.d_ptr,
970
fixup_addr(read_word(element->d_un.d_ptr)));
973
rel_size = get_dynamic_val(dynamic, DT_RELSZ);
974
rel_entry_size = get_dynamic_val(dynamic, DT_RELENT);
975
rel = (Elf32_Rel *)FILE_OFFSET(vma_to_offset(read_word(element->d_un.d_ptr)));
976
remap_rel_section(rel, rel_size, rel_entry_size);
978
write_word(&element->d_un.d_ptr,
979
fixup_addr(read_word(element->d_un.d_ptr)));
982
rel_size = get_dynamic_val(dynamic, DT_RELASZ);
983
rel_entry_size = get_dynamic_val(dynamic, DT_RELAENT);
984
rela = (Elf32_Rela *)FILE_OFFSET(vma_to_offset(read_word(element->d_un.d_ptr)));
985
remap_rela_section(rela, rel_size, rel_entry_size);
987
write_word(&element->d_un.d_ptr,
988
fixup_addr(read_word(element->d_un.d_ptr)));
991
/*printf("unhandled d_tag: %d (0x%x)\n", read_sword(element->d_tag), read_sword(element->d_tag));*/
995
element = (Elf32_Dyn *)((char *)element + entry_size);
1000
align_hole(Elf32_Word *start, Elf32_Word *end)
1004
Elf32_Shdr *section;
1005
Elf32_Word sectionsize;
1010
len = *end - *start;
1013
sectionsize = read_half(elf_header->e_shentsize);
1014
numsections = read_half(elf_header->e_shnum);
1016
section = (Elf32_Shdr *)FILE_OFFSET(read_word(elf_header->e_shoff));
1019
for (i=0;i<numsections;i++) {
1020
if ( (read_word(section->sh_addralign) > 1) &&
1021
( (read_word(section->sh_offset) - len + align)%read_word(section->sh_addralign) != 0) ) {
1025
section = (Elf32_Shdr *)((char *)section + sectionsize);
1032
} while (unaligned);
1038
main(int argc, char *argv[])
1041
unsigned char *mapping;
1043
struct stat statbuf;
1044
Elf32_Shdr *dynamic;
1049
Elf32_Shdr *higher_section;
1050
Elf32_Word dynstr_index;
1054
unsigned char *new_dynstr;
1055
Elf32_Word old_dynstr_size;
1056
Elf32_Word new_dynstr_size;
1059
fprintf(stderr, "Usage: %s <filename>\n", argv[0]);
1063
fd = open(argv[1], O_RDWR);
1065
fprintf(stderr, "Cannot open file %s\n", argv[1]);
1069
if (fstat(fd, &statbuf) == -1) {
1070
fprintf(stderr, "Cannot stat file %s\n", argv[1]);
1074
size = statbuf.st_size;
1076
mapping = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1078
if (mapping == (unsigned char *)-1) {
1079
fprintf(stderr, "Cannot mmap file %s\n", argv[1]);
1083
used_dynamic_symbols = g_hash_table_new(g_direct_hash, g_direct_equal);
1085
elf_header = (Elf32_Ehdr *)mapping;
1087
if (strncmp((void *)elf_header, ELFMAG, SELFMAG)!=0) {
1088
fprintf(stderr, "Not an ELF file\n");
1092
if (elf_header->e_ident[EI_VERSION] != EV_CURRENT) {
1093
fprintf(stderr, "Wrong ELF file version\n");
1097
if (elf_header->e_ident[EI_CLASS] != ELFCLASS32) {
1098
fprintf(stderr, "Only 32bit ELF files supported\n");
1102
setup_byteswapping(elf_header->e_ident[EI_DATA]);
1104
machine_type = read_half(elf_header->e_machine);
1105
if ( (machine_type != EM_386) &&
1106
(machine_type != EM_PPC) ) {
1107
fprintf(stderr, "Unsupported architecture. Supported are: x86, ppc\n");
1111
if (read_half(elf_header->e_type) != ET_DYN) {
1112
fprintf(stderr, "Not an ELF shared object\n");
1116
dynamic = elf_find_section(SHT_DYNAMIC);
1117
dynsym = elf_find_section(SHT_DYNSYM);
1118
symtab = elf_find_section(SHT_SYMTAB);
1119
dynstr_index = read_word(dynsym->sh_link);
1120
dynstr = elf_find_section_num(dynstr_index);
1121
dynstr_data = (char *)FILE_OFFSET(read_word(dynstr->sh_offset));
1122
old_dynstr_size = read_word(dynstr->sh_size);
1123
ver_d = elf_find_section(SHT_GNU_verdef);
1124
ver_r = elf_find_section(SHT_GNU_verneed);
1125
hash = elf_find_section(SHT_HASH);
1127
/* Generate hash table with all used strings: */
1129
add_strings_from_dynsym(dynsym, dynstr_data);
1130
add_strings_from_dynamic(dynamic, dynstr_data);
1131
if (ver_d && (read_word(ver_d->sh_link) == dynstr_index))
1132
add_strings_from_ver_d(ver_d, dynstr_data);
1133
if (ver_r && (read_word(ver_r->sh_link) == dynstr_index))
1134
add_strings_from_ver_r(ver_r, dynstr_data);
1136
/* Generate new dynstr section from the used strings hashtable: */
1138
new_dynstr = generate_new_dynstr(&new_dynstr_size);
1140
printf("New dynstr size: %d\n", new_dynstr_size);
1141
printf("Old dynstr size: %d\n", old_dynstr_size);
1144
if (new_dynstr_size >= old_dynstr_size) {
1148
/* Fixup all references: */
1149
fixup_strings_in_dynsym(dynsym);
1150
fixup_strings_in_dynamic(dynamic);
1151
if (ver_d && (read_word(ver_d->sh_link) == dynstr_index))
1152
fixup_strings_in_ver_d(ver_d);
1153
if (ver_r && (read_word(ver_r->sh_link) == dynstr_index))
1154
fixup_strings_in_ver_r(ver_r);
1156
/* Copy over the new dynstr: */
1157
memcpy(dynstr_data, new_dynstr, new_dynstr_size);
1158
memset(dynstr_data + new_dynstr_size, ' ', old_dynstr_size-new_dynstr_size);
1160
/* Compact the dynstr section and the file: */
1162
/* 1. Set up the data for the fixup_offset() function: */
1163
hole_index = read_word(dynstr->sh_offset) + new_dynstr_size;
1164
higher_section = elf_find_next_higher_section(hole_index);
1165
hole_end = read_word(higher_section->sh_offset);
1167
align_hole(&hole_index, &hole_end);
1168
hole_len = hole_end - hole_index;
1170
hole_addr_start = hole_index; /* TODO: Fix this to something better */
1172
find_segment_addr_min_max(read_word(dynstr->sh_offset),
1173
&hole_addr_remap_start, &hole_addr_remap_end);
1176
printf("Hole remap: 0x%lx - 0x%lx\n", hole_addr_remap_start, hole_addr_remap_end);
1178
printf("hole: %lu - %lu (%lu bytes)\n", hole_index, hole_end, hole_len);
1179
printf("hole: 0x%lx - 0x%lx (0x%lx bytes)\n", hole_index, hole_end, hole_len);
1182
/* 2. Change all section and segment sizes and offsets: */
1183
remap_symtab(dynsym);
1185
remap_symtab(symtab);
1187
if (machine_type == EM_386)
1189
if (machine_type == EM_PPC)
1192
remap_dynamic(dynamic, new_dynstr_size);
1193
remap_sections(); /* After this line the section headers are wrong */
1197
/* 3. Do the real compacting. */
1199
memmove(mapping + hole_index,
1200
mapping + hole_index + hole_len,
1201
size - (hole_index + hole_len));
1203
munmap(mapping, size);
1205
ftruncate(fd, size - hole_len);