17 #define DT_VERNEEDED 0x6ffffffe
18 #define DT_VERNEEDNUM 0x6fffffff
20 template<typename ElfHeaderType
/*Elf{32,64}_Ehdr*/,
21 typename ElfSectionHeaderType
/*Elf{32,64}_Shdr*/,
22 typename ElfDynamicSectionEntryType
/* Elf{32,64}_Dyn */>
23 bool process_elf(uint8_t* bytes
, size_t elf_file_size
)
25 if (sizeof(ElfSectionHeaderType
) > elf_file_size
) {
26 fprintf(stderr
, "ERROR: Elf header would end at %lu but file size only %lu\n", sizeof(ElfSectionHeaderType
), elf_file_size
);
29 ElfHeaderType
* elf_hdr
= reinterpret_cast<ElfHeaderType
*>(bytes
);
31 size_t last_section_header_byte
= elf_hdr
->e_shoff
+ sizeof(ElfSectionHeaderType
) * elf_hdr
->e_shnum
;
32 if (last_section_header_byte
> elf_file_size
) {
33 fprintf(stderr
, "ERROR: Section header would end at %lu but file size only %lu\n", last_section_header_byte
, elf_file_size
);
36 ElfSectionHeaderType
* section_header_table
= reinterpret_cast<ElfSectionHeaderType
*>(bytes
+ elf_hdr
->e_shoff
);
38 for (unsigned int i
= 1; i
< elf_hdr
->e_shnum
; i
++) {
39 ElfSectionHeaderType
* section_header_entry
= section_header_table
+ i
;
40 if (section_header_entry
->sh_type
== SHT_DYNAMIC
) {
41 size_t const last_dynamic_section_byte
= section_header_entry
->sh_offset
+ section_header_entry
->sh_size
;
42 if (last_dynamic_section_byte
> elf_file_size
) {
43 fprintf(stderr
, "ERROR: Dynamic section would end at %lu but file size only %lu\n", last_dynamic_section_byte
, elf_file_size
);
47 size_t const dynamic_section_entries
= section_header_entry
->sh_size
/ sizeof(ElfDynamicSectionEntryType
);
48 ElfDynamicSectionEntryType
* const dynamic_section
=
49 reinterpret_cast<ElfDynamicSectionEntryType
*>(bytes
+ section_header_entry
->sh_offset
);
51 unsigned int last_nonnull_entry_idx
= 0;
52 for (unsigned int j
= dynamic_section_entries
- 1; j
> 0; j
--) {
53 ElfDynamicSectionEntryType
* dynamic_section_entry
= dynamic_section
+ j
;
54 if (dynamic_section_entry
->d_tag
!= DT_NULL
) {
55 last_nonnull_entry_idx
= j
;
60 for (unsigned int j
= 0; j
< dynamic_section_entries
; j
++) {
61 ElfDynamicSectionEntryType
* dynamic_section_entry
= dynamic_section
+ j
;
62 switch (dynamic_section_entry
->d_tag
) {
67 char const* removed_name
;
68 switch (dynamic_section_entry
->d_tag
) {
69 case DT_VERNEEDED
: removed_name
= "DT_VERNEEDED"; break;
70 case DT_VERNEEDNUM
: removed_name
= "DT_VERNEEDNUM"; break;
71 case DT_RPATH
: removed_name
= "DT_RPATH"; break;
72 case DT_RUNPATH
: removed_name
= "DT_RUNPATH"; break;
74 printf("Removing the %s dynamic section entry\n", removed_name
);
75 // Tag the entry with DT_NULL and put it last:
76 dynamic_section_entry
->d_tag
= DT_NULL
;
77 // Decrease j to process new entry index:
78 std
::swap(dynamic_section
[j
--], dynamic_section
[last_nonnull_entry_idx
--]);
88 int main(int argc
, char **argv
)
90 if (argc
< 2 || (argc
== 2 && strcmp(argv
[1], "-h")==0)) {
91 fprintf(stderr
, "usage: %s <filename>\n", argv
[0]);
92 fprintf(stderr
, " Processes ELF files to remove DT_VERNEEDED, DT_VERNEEDNUM, DT_RPATH\n"
93 " and DT_RUNPATH entries (which the Android linker warns about)\n");
97 for (int i
= 1; i
< argc
; i
++) {
98 int fd
= open(argv
[i
], O_RDWR
);
99 if (fd
< 0) { perror("open()"); return 1; }
102 if (fstat(fd
, &st
) < 0) { perror("fstat()"); return 1; }
104 if (st
.st_size
< (long long) sizeof(Elf32_Ehdr
)) continue;
106 void* mem
= mmap(0, st
.st_size
, PROT_READ
| PROT_WRITE
, MAP_SHARED
, fd
, 0);
107 if (mem
== MAP_FAILED
) { perror("mmap()"); return 1; }
109 uint8_t* bytes
= reinterpret_cast<uint8_t*>(mem
);
110 if (!(bytes
[0] == 0x7F && bytes
[1] == 'E' && bytes
[2] == 'L' && bytes
[3] == 'F')) {
111 munmap(mem
, st
.st_size
);
116 uint8_t bit_value
= bytes
[4];
117 if (!(bit_value
== 1 || bit_value
== 2)) {
118 printf("ERROR: Incorrect bit value: %d\n", bit_value
);
120 } else if (bit_value
== 1) {
121 if (!process_elf
<Elf32_Ehdr
, Elf32_Shdr
, Elf32_Dyn
>(bytes
, st
.st_size
)) return 1;
123 if (!process_elf
<Elf64_Ehdr
, Elf64_Shdr
, Elf64_Dyn
>(bytes
, st
.st_size
)) return 1;
126 if (msync(mem
, st
.st_size
, MS_SYNC
) < 0) { perror("msync()"); return 1; }
128 munmap(mem
, st
.st_size
);