10
10
#include <unistd.h>
11
11
12
12
#ifdef __aarch64__
13
- #define PAGE_SIZE 0x10000
14
13
#define MACHINE EM_AARCH64
15
14
#endif
16
15
#ifdef __x86_64__
17
- #define PAGE_SIZE 0x1000
18
16
#define MACHINE EM_X86_64
19
17
#endif
20
18
@@ -51,6 +49,7 @@ typedef struct Analysis Analysis;
51
49
struct Analysis {
52
50
Elf64_Phdr * pt_interp ;
53
51
Elf64_Addr max_vaddr ;
52
+ Elf64_Addr max_align ;
54
53
};
55
54
56
55
typedef struct ProgramHeaders ProgramHeaders ;
@@ -127,12 +126,15 @@ Analysis elf_analyze (Elf elf) {
127
126
Elf64_Phdr * end = itr + elf .ehdr -> e_phnum ;
128
127
int i = 0 ;
129
128
for (; itr != end ; itr ++ ) {
130
- if (itr -> p_type ! = PT_LOAD ) {
129
+ if (itr -> p_type = = PT_LOAD ) {
131
130
Elf64_Addr end_of_segment = itr -> p_vaddr + itr -> p_memsz ;
132
131
TRACE ("phdr[%d] vaddr:%lx memsz:%lx, end:%lx" , i ++ , itr -> p_vaddr , itr -> p_memsz , end_of_segment );
133
132
if (end_of_segment > analysis .max_vaddr ) {
134
133
analysis .max_vaddr = end_of_segment ;
135
134
}
135
+ if (itr -> p_align > analysis .max_align ) {
136
+ analysis .max_align = itr -> p_align ;
137
+ }
136
138
}
137
139
if (itr -> p_type == PT_INTERP ) {
138
140
ABORT_IF (analysis .pt_interp , "multiple interpreters found" );
@@ -143,6 +145,35 @@ Analysis elf_analyze (Elf elf) {
143
145
return analysis ;
144
146
}
145
147
148
+
149
+ // Bubble sort loadable segments
150
+ void elf_sort_segments (Elf64_Phdr * phdr , size_t num ) {
151
+ TRACE ("num segments = %d" , num );
152
+ Elf64_Addr start_addr , end_addr ;
153
+ for (;;) {
154
+ bool swapped = false;
155
+ for (int n = 0 ; n < (num - 1 ); n ++ ) {
156
+ end_addr = phdr [n ].p_vaddr + phdr [n ].p_memsz ;
157
+ start_addr = phdr [n + 1 ].p_vaddr ;
158
+ TRACE ("phdr[%d].start = %lx, phdr[%d].end = %lx, phdr[%d].start = %lx" , n , phdr [n ].p_vaddr , n , end_addr , n + 1 , start_addr );
159
+ ABORT_IF (start_addr >= phdr [n ].p_vaddr && start_addr < end_addr , "invalid program headers" );
160
+ if (end_addr > start_addr ) {
161
+ TRACE ("swap phdr[%d], phdr[%d]" , n , n + 1 );
162
+ Elf64_Phdr tmp = phdr [n ];
163
+ phdr [n ] = phdr [n + 1 ];
164
+ phdr [n + 1 ] = tmp ;
165
+ swapped = true;
166
+ TRACE ("swapped %d and %d" , n , n + 1 );
167
+ } else {
168
+ TRACE ("skipping %d" , n );
169
+ }
170
+ }
171
+ if (!swapped ) {
172
+ break ;
173
+ }
174
+ }
175
+ }
176
+
146
177
int main (int argc , const char * * argv ) {
147
178
TRACING_ENABLED = getenv ("TANGRAM_TRACING" ) != NULL ;
148
179
@@ -207,20 +238,22 @@ int main (int argc, const char** argv) {
207
238
208
239
// Compute the offset/size of the stub binary.
209
240
size_t stub_offs = headers .phdr
210
- ? ALIGN (headers .offs + headers .sz , PAGE_SIZE )
211
- : ALIGN (output .sz , PAGE_SIZE );
212
- size_t stub_sz = ALIGN (stub_bin .sz , PAGE_SIZE );
241
+ ? ALIGN (headers .offs + headers .sz , analysis . max_align )
242
+ : ALIGN (output .sz , analysis . max_align );
243
+ size_t stub_sz = ALIGN (stub_bin .sz , analysis . max_align );
213
244
214
245
// Create segment for the stub.
215
246
stub_segment -> p_type = PT_LOAD ;
216
247
stub_segment -> p_flags = PF_R | PF_X ;
217
- stub_segment -> p_align = 0x1000 ;
248
+ stub_segment -> p_align = analysis . max_align ;
218
249
stub_segment -> p_offset = stub_offs ;
219
- stub_segment -> p_paddr = analysis .max_vaddr ;
220
- stub_segment -> p_vaddr = analysis .max_vaddr ;
250
+ stub_segment -> p_paddr = ALIGN ( analysis .max_vaddr , analysis . max_align ) ;
251
+ stub_segment -> p_vaddr = ALIGN ( analysis .max_vaddr , analysis . max_align ) ;
221
252
stub_segment -> p_filesz = stub_sz ;
222
253
stub_segment -> p_memsz = stub_sz ;
223
254
255
+ TRACE ("new segment vaddr: %lx, memsz: %lx" , stub_segment -> p_vaddr , stub_segment -> p_memsz );
256
+
224
257
// Create the footer.
225
258
Footer footer = {
226
259
.size = manifest .sz ,
@@ -230,12 +263,26 @@ int main (int argc, const char** argv) {
230
263
231
264
// Update the entrypoint.
232
265
TRACE ("%s entrypoint:%lx" , stub_elf .path , stub_exe .ehdr -> e_entry );
233
- output_exe .ehdr -> e_entry = analysis . max_vaddr + stub_exe .ehdr -> e_entry ;
266
+ output_exe .ehdr -> e_entry = stub_segment -> p_vaddr + stub_exe .ehdr -> e_entry ;
234
267
235
268
// Patch the program header table if necessary.
236
269
if (headers .phdr ) {
237
270
output_exe .ehdr -> e_phoff = headers .offs ;
238
271
output_exe .ehdr -> e_phnum = headers .num ;
272
+ } else {
273
+ // Sort program headers.
274
+ Elf64_Phdr * start = NULL ;
275
+ size_t num = 0 ;
276
+ for (int i = 0 ; i < output_exe .ehdr -> e_phnum ; i ++ ) {
277
+ if (output_exe .phdr [i ].p_type != PT_LOAD ) {
278
+ continue ;
279
+ }
280
+ if (!start ) {
281
+ start = & output_exe .phdr [i ];
282
+ }
283
+ num ++ ;
284
+ }
285
+ elf_sort_segments (start , num );
239
286
}
240
287
241
288
// Close elf objects.
0 commit comments