@@ -162,6 +162,17 @@ static inline void amd64_rewrite_rip_symbol(amd64_asm_operand_t *operand) {
162
162
operand -> value = r ;
163
163
}
164
164
165
+ static inline void amd64_rewrite_fs_offset_symbol (amd64_asm_operand_t * operand ) {
166
+ operand -> type = AMD64_ASM_OPERAND_TYPE_SEG_OFFSET ;
167
+ operand -> size = operand -> size ;
168
+
169
+ asm_seg_offset_t * s = NEW (asm_seg_offset_t );
170
+ s -> name = "fs" ;
171
+ s -> offset = 0 ;
172
+ operand -> value = s ;
173
+ }
174
+
175
+
165
176
static inline amd64_asm_operand_t * extract_symbol_operand (amd64_asm_inst_t * operation ) {
166
177
for (int i = 0 ; i < operation -> count ; ++ i ) {
167
178
amd64_asm_operand_t * operand = operation -> operands [i ];
@@ -192,11 +203,13 @@ static inline int amd64_gotplt_entry_type(uint64_t relocate_type) {
192
203
case R_X86_64_JUMP_SLOT :
193
204
case R_X86_64_COPY :
194
205
case R_X86_64_RELATIVE :
206
+ case R_X86_64_TPOFF32 :
207
+ case R_X86_64_TPOFF64 :
195
208
return NO_GOTPLT_ENTRY ;
196
209
197
- /* The following relocs wouldn't normally need GOT or PLT
198
- slots, but we need them for simplicity in the link
199
- editor part. See our caller for comments. */
210
+ /* The following relocs wouldn't normally need GOT or PLT
211
+ slots, but we need them for simplicity in the link
212
+ editor part. See our caller for comments. */
200
213
case R_X86_64_32 :
201
214
case R_X86_64_32S :
202
215
case R_X86_64_64 :
@@ -217,9 +230,9 @@ static inline int amd64_gotplt_entry_type(uint64_t relocate_type) {
217
230
case R_X86_64_TLSGD :
218
231
case R_X86_64_TLSLD :
219
232
case R_X86_64_DTPOFF32 :
220
- case R_X86_64_TPOFF32 :
233
+ // case R_X86_64_TPOFF32:
221
234
case R_X86_64_DTPOFF64 :
222
- case R_X86_64_TPOFF64 :
235
+ // case R_X86_64_TPOFF64:
223
236
case R_X86_64_REX_GOTPCRELX :
224
237
case R_X86_64_PLT32 :
225
238
case R_X86_64_PLTOFF64 :
@@ -277,11 +290,12 @@ static inline int8_t amd64_is_code_relocate(uint64_t relocate_type) {
277
290
case R_X86_64_TLSGD :
278
291
case R_X86_64_TLSLD :
279
292
case R_X86_64_DTPOFF32 :
280
- case R_X86_64_TPOFF32 :
293
+ // case R_X86_64_TPOFF32:
281
294
case R_X86_64_DTPOFF64 :
282
295
case R_X86_64_TPOFF64 :
283
296
return 0 ;
284
297
298
+ // case R_X86_64_TPOFF32:
285
299
case R_X86_64_PC32 :
286
300
case R_X86_64_PC64 :
287
301
case R_X86_64_PLT32 :
@@ -311,7 +325,8 @@ elf_amd64_relocate(elf_context_t *ctx, Elf64_Rela *rel, int type, uint8_t *ptr,
311
325
case R_X86_64_PLT32 :
312
326
/* fallthrough: val already holds the PLT slot address */
313
327
314
- plt32pc32 : {
328
+ plt32pc32 :
329
+ {
315
330
// 相对地址计算,
316
331
// addr 保存了符号的使用位置(加载到虚拟内存中的位置)
317
332
// val 保存了符号的定义的位置(加载到虚拟内存中的位置)
@@ -323,7 +338,8 @@ elf_amd64_relocate(elf_context_t *ctx, Elf64_Rela *rel, int type, uint8_t *ptr,
323
338
}
324
339
// 小端写入
325
340
add32le (ptr , diff );
326
- } break ;
341
+ }
342
+ break ;
327
343
328
344
case R_X86_64_COPY :
329
345
break ;
@@ -345,7 +361,7 @@ elf_amd64_relocate(elf_context_t *ctx, Elf64_Rela *rel, int type, uint8_t *ptr,
345
361
case R_X86_64_GOTPCRELX :
346
362
case R_X86_64_REX_GOTPCRELX :
347
363
add32le (ptr , ctx -> got -> sh_addr - addr +
348
- elf_get_sym_attr (ctx , sym_index , 0 )-> got_offset - 4 );
364
+ elf_get_sym_attr (ctx , sym_index , 0 )-> got_offset - 4 );
349
365
break ;
350
366
case R_X86_64_GOTPC32 :
351
367
add32le (ptr , ctx -> got -> sh_addr - addr + rel -> r_addend );
@@ -420,9 +436,11 @@ elf_amd64_relocate(elf_context_t *ctx, Elf64_Rela *rel, int type, uint8_t *ptr,
420
436
case R_X86_64_TPOFF32 : {
421
437
Elf64_Sym * sym = & ((Elf64_Sym * ) ctx -> symtab_section -> data )[sym_index ];
422
438
section_t * s = SEC_TACK (sym -> st_shndx );
423
- int32_t x ;
424
439
425
- x = val - s -> sh_addr - s -> data_count ;
440
+ int32_t x = - val ;
441
+ log_debug ("[elf_amd64_relocate] R_X86_64_TPOFF32, val=%ld, s->sh_addr=%ld, s->data_count=%ld, x=%lx" , val ,
442
+ s -> sh_addr , s -> data_count , (uint32_t )x );
443
+
426
444
add32le (ptr , x );
427
445
break ;
428
446
}
@@ -517,6 +535,11 @@ static inline void elf_amd64_operation_encodings(elf_context_t *ctx, slice_t *cl
517
535
temp -> rel_symbol = symbol_operand -> name ;
518
536
}
519
537
} else {
538
+ int st_type = STT_OBJECT ;
539
+ if (symbol_operand -> is_tls ) {
540
+ st_type = STT_TLS ;
541
+ }
542
+
520
543
// 其他指令(可能是 mov 等,对数据段符号的引用)引用了符号,由于不用考虑指令重写的问题,所以直接写入 0(%rip),让重定位阶段去找改符号进行重定位即可
521
544
// 完全不用考虑是标签符号还是数据符号
522
545
// 添加到重定位表(.rela.text)
@@ -527,15 +550,21 @@ static inline void elf_amd64_operation_encodings(elf_context_t *ctx, slice_t *cl
527
550
Elf64_Sym sym = {
528
551
.st_shndx = 0 ,
529
552
.st_size = 0 ,
530
- .st_info = ELF64_ST_INFO (STB_GLOBAL , STT_FUNC ),
553
+ .st_info = ELF64_ST_INFO (STB_GLOBAL , st_type ),
531
554
.st_other = 0 ,
532
555
.st_value = 0 ,
533
556
};
534
557
sym_index = elf_put_sym (ctx -> symtab_section , ctx -> symtab_hash , & sym , symbol_operand -> name );
535
558
}
536
559
537
- // rewrite symbol TODO 可能有其他的重定位方式
538
- amd64_rewrite_rip_symbol (rel_operand );
560
+ int reloc_type = 0 ;
561
+ if (symbol_operand -> is_tls ) {
562
+ amd64_rewrite_fs_offset_symbol (rel_operand );
563
+ reloc_type = R_X86_64_TPOFF32 ;
564
+ } else {
565
+ amd64_rewrite_rip_symbol (rel_operand );
566
+ reloc_type = R_X86_64_PC32 ;
567
+ }
539
568
540
569
// 编码
541
570
temp -> inst = amd64_asm_inst_encoding (* operation , temp -> data , & temp -> data_count , c );
@@ -544,12 +573,18 @@ static inline void elf_amd64_operation_encodings(elf_context_t *ctx, slice_t *cl
544
573
545
574
// 将符号和 sym_index 关联,rel 记录了符号的使用位置, sym_index 记录的符号的信息(包括 linker 完成后的绝对虚拟地址)
546
575
// 计算重定位的起点信息
576
+ // rip_offset 和 seg_offset 都是最后 4 个字节
547
577
uint64_t rel_offset = * temp -> offset + rip_offset (temp -> data_count , temp -> operation );
548
- int64_t addend = (int64_t ) (* temp -> offset + temp -> data_count ) - (int64_t ) rel_offset ;
578
+ int64_t addend = 0 ;
579
+ if (symbol_operand -> is_tls ) {
580
+ addend = 0 ;
581
+ } else {
582
+ addend = (int64_t ) (* temp -> offset + temp -> data_count ) - (int64_t ) rel_offset ;
583
+ }
549
584
550
585
// addend = 下一条指令的起始位置 - rel_offset
551
586
temp -> rel = elf_put_relocate (ctx , ctx -> symtab_section , ctx -> text_section ,
552
- rel_offset , R_X86_64_PC32 , (int ) sym_index , - addend );
587
+ rel_offset , reloc_type , (int ) sym_index , - addend );
553
588
554
589
continue ;
555
590
}
@@ -679,7 +714,9 @@ static void mach_amd64_operation_encodings(mach_context_t *ctx, slice_t *closure
679
714
if (!s -> is_local ) {
680
715
n_type |= N_EXT ;
681
716
}
682
- uint64_t sym_index = mach_put_sym (ctx -> symtab_command , & (struct nlist_64 ){.n_sect = ctx -> text_section -> sh_index , .n_value = * temp -> offset , .n_type = n_type }, s -> name );
717
+ uint64_t sym_index = mach_put_sym (ctx -> symtab_command ,
718
+ & (struct nlist_64 ) {.n_sect = ctx -> text_section -> sh_index , .n_value = * temp -> offset , .n_type = n_type },
719
+ s -> name );
683
720
temp -> sym_index = sym_index ;
684
721
685
722
assert (s -> name );
@@ -722,7 +759,11 @@ static void mach_amd64_operation_encodings(mach_context_t *ctx, slice_t *closure
722
759
uint64_t sym_index = (uint64_t ) table_get (symtab_hash , symbol_operand -> name );
723
760
if (sym_index == 0 ) {
724
761
// 可重定位符号注册
725
- sym_index = mach_put_sym (ctx -> symtab_command , & (struct nlist_64 ){.n_sect = NO_SECT , .n_value = 0 , .n_type = N_UNDF | N_EXT }, symbol_operand -> name );
762
+ sym_index = mach_put_sym (ctx -> symtab_command , & (struct nlist_64 ) {
763
+ .n_sect = NO_SECT ,
764
+ .n_value = 0 ,
765
+ .n_type = N_UNDF | N_EXT
766
+ }, symbol_operand -> name );
726
767
}
727
768
728
769
// rewrite symbol
@@ -738,8 +779,14 @@ static void mach_amd64_operation_encodings(mach_context_t *ctx, slice_t *closure
738
779
uint64_t rel_offset = * temp -> offset + rip_offset (temp -> data_count , temp -> operation );
739
780
int64_t addend = (int64_t ) (* temp -> offset + temp -> data_count ) - (int64_t ) rel_offset ; // 下一条指令的其实位置
740
781
782
+ bool is_tls = symbol_operand -> is_tls ;
783
+ int reloc_type = X86_64_RELOC_BRANCH ;
784
+ if (is_tls ) {
785
+ reloc_type = X86_64_RELOC_TLV ;
786
+ }
787
+
741
788
// addend = 下一条指令的起始位置 - rel_offset, 这是一条 branch 类型的数据
742
- temp -> rel = mach_put_relocate (ctx , ctx -> text_section , rel_offset , X86_64_RELOC_BRANCH , sym_index );
789
+ temp -> rel = mach_put_relocate (ctx , ctx -> text_section , rel_offset , reloc_type , sym_index );
743
790
continue ;
744
791
}
745
792
}
@@ -786,7 +833,9 @@ static void mach_amd64_operation_encodings(mach_context_t *ctx, slice_t *closure
786
833
if (sym_index == 0 ) {
787
834
// 如果遍历没有找到符号则会添加一条 UND 符号信息到符号表中
788
835
// 10: 0000000000000000 0 FUNC GLOBAL DEFAULT UND string_new
789
- sym_index = mach_put_sym (ctx -> symtab_command , & (struct nlist_64 ){.n_sect = NO_SECT , .n_value = 0 , .n_type = N_UNDF | N_EXT }, temp -> rel_symbol );
836
+ sym_index = mach_put_sym (ctx -> symtab_command ,
837
+ & (struct nlist_64 ) {.n_sect = NO_SECT , .n_value = 0 , .n_type = N_UNDF | N_EXT },
838
+ temp -> rel_symbol );
790
839
}
791
840
792
841
// sym->st_value 表示符号定义的位置,基于符号所在的 section(.section)
0 commit comments