Skip to content

Commit b0c4301

Browse files
committed
lk
1 parent bf932c0 commit b0c4301

4 files changed

Lines changed: 353 additions & 224 deletions

File tree

src/linker_elf.ds

Lines changed: 156 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,13 @@ forge ElfFormat {
5555
const R_X86_64_GOTPCREL: UInt32 = 9;
5656
const R_X86_64_32: UInt32 = 10;
5757
const R_X86_64_32S: UInt32 = 11;
58+
const R_X86_64_PC64: UInt32 = 24;
5859
const R_X86_64_GOTPCRELX: UInt32 = 41;
5960
const R_X86_64_REX_GOTPCRELX: UInt32 = 42;
6061
const R_AARCH64_NONE: UInt32 = 0;
6162
const R_AARCH64_ABS64: UInt32 = 257;
6263
const R_AARCH64_ABS32: UInt32 = 258;
64+
const R_AARCH64_PREL64: UInt32 = 260;
6365
const R_AARCH64_PREL32: UInt32 = 261;
6466

6567
const ELF64_HEADER_SIZE: UInt32 = 64;
@@ -206,7 +208,10 @@ forge ElfFormat {
206208
if reloc_type == R_X86_64_GOTPCREL {
207209
return 0;
208210
} else {
209-
if reloc_type == R_X86_64_GOTPCRELX {
211+
if reloc_type == R_X86_64_PC64 {
212+
return 0;
213+
} else {
214+
if reloc_type == R_X86_64_GOTPCRELX {
210215
return 0;
211216
} else {
212217
if reloc_type == R_X86_64_REX_GOTPCRELX {
@@ -215,6 +220,7 @@ forge ElfFormat {
215220
return 6;
216221
}
217222
}
223+
}
218224
}
219225
}
220226
}
@@ -441,11 +447,7 @@ forge ElfFormat {
441447
if offset >= section_size {
442448
return 6;
443449
} else {
444-
if addend > 9223372036854775807 {
445-
return 6;
446-
} else {
447-
return 0;
448-
}
450+
return 0;
449451
}
450452
}
451453
}
@@ -461,11 +463,15 @@ forge ElfFormat {
461463
if reloc_type == R_AARCH64_ABS32 {
462464
return 0;
463465
} else {
464-
if reloc_type == R_AARCH64_PREL32 {
466+
if reloc_type == R_AARCH64_PREL64 {
467+
return 0;
468+
} else {
469+
if reloc_type == R_AARCH64_PREL32 {
465470
return 0;
466471
} else {
467472
return 6;
468473
}
474+
}
469475
}
470476
}
471477
}
@@ -566,6 +572,73 @@ forge ElfFormat {
566572
return r_info - (sym * 4294967296);
567573
}
568574

575+
proc K::implicit_rel_addend_width(reloc_type: UInt32, machine: UInt16) -> UInt32 {
576+
if machine == EM_X86_64 {
577+
if reloc_type == R_X86_64_64 {
578+
return 8;
579+
} else {
580+
if reloc_type == R_X86_64_GLOB_DAT {
581+
return 8;
582+
} else {
583+
if reloc_type == R_X86_64_JUMP_SLOT {
584+
return 8;
585+
} else {
586+
if reloc_type == R_X86_64_RELATIVE {
587+
return 8;
588+
} else {
589+
if reloc_type == R_X86_64_PC64 {
590+
return 8;
591+
} else {
592+
return 4;
593+
}
594+
}
595+
}
596+
}
597+
}
598+
}
599+
if machine == EM_AARCH64 {
600+
if reloc_type == R_AARCH64_ABS64 {
601+
return 8;
602+
} else {
603+
if reloc_type == R_AARCH64_PREL64 {
604+
return 8;
605+
} else {
606+
return 4;
607+
}
608+
}
609+
}
610+
return 4;
611+
}
612+
613+
proc K::read_implicit_rel_addend(
614+
path: UInt64,
615+
machine: UInt16,
616+
target_section_type: UInt32,
617+
target_section_off: UInt64,
618+
target_section_size: UInt64,
619+
reloc_offset: UInt64,
620+
reloc_type: UInt32
621+
) -> UInt64 {
622+
if target_section_type == SHT_NOBITS {
623+
return 0;
624+
} else {
625+
let width = implicit_rel_addend_width(reloc_type, machine);
626+
if width == 8 {
627+
if reloc_offset + 8 > target_section_size {
628+
return 0;
629+
} else {
630+
return read_u64_file(path, target_section_off + reloc_offset);
631+
}
632+
} else {
633+
if reloc_offset + 4 > target_section_size {
634+
return 0;
635+
} else {
636+
return read_u32_file(path, target_section_off + reloc_offset);
637+
}
638+
}
639+
}
640+
}
641+
569642
proc K::ingest_symbol_records(
570643
path: UInt64,
571644
sym_off: UInt64,
@@ -681,6 +754,77 @@ forge ElfFormat {
681754
}
682755
}
683756

757+
proc K::ingest_relocation_records_rel(
758+
path: UInt64,
759+
machine: UInt16,
760+
reloc_off: UInt64,
761+
reloc_entsize: UInt64,
762+
reloc_count: UInt32,
763+
index: UInt32,
764+
target_section: UInt32,
765+
target_section_size: UInt64,
766+
target_section_type: UInt32,
767+
target_section_off: UInt64,
768+
symbol_count: UInt32
769+
) -> UInt32 {
770+
if index >= reloc_count {
771+
return 0;
772+
} else {
773+
let rec_off = reloc_off + (index * reloc_entsize);
774+
let r_offset = read_u64_file(path, rec_off + 0);
775+
let r_info = read_u64_file(path, rec_off + 8);
776+
let sym_index = decode_r_info_sym(r_info);
777+
let reloc_type = decode_r_info_type(r_info);
778+
let r_addend = read_implicit_rel_addend(
779+
path,
780+
machine,
781+
target_section_type,
782+
target_section_off,
783+
target_section_size,
784+
r_offset,
785+
reloc_type
786+
);
787+
788+
let validate_status = parse_relocation_record_fields(
789+
r_offset,
790+
reloc_type,
791+
machine,
792+
sym_index,
793+
r_addend,
794+
target_section_size,
795+
symbol_count
796+
);
797+
if validate_status ! 0 {
798+
return validate_status;
799+
} else {
800+
let register_status = host_linker_object_add_relocation(
801+
target_section,
802+
r_offset,
803+
reloc_type,
804+
sym_index,
805+
r_addend
806+
);
807+
if register_status ! 0 {
808+
return register_status;
809+
} else {
810+
return ingest_relocation_records_rel(
811+
path,
812+
machine,
813+
reloc_off,
814+
reloc_entsize,
815+
reloc_count,
816+
index + 1,
817+
target_section,
818+
target_section_size,
819+
target_section_type,
820+
target_section_off,
821+
symbol_count
822+
);
823+
}
824+
}
825+
}
826+
}
827+
684828
proc K::ingest_section_records(
685829
path: UInt64,
686830
machine: UInt16,
@@ -767,9 +911,11 @@ forge ElfFormat {
767911
let symbol_table_size_rel = section_size(path, shoff, shentsize, sec_link);
768912
let symbol_table_entsize_rel = section_entsize(path, shoff, shentsize, sec_link);
769913
let symbol_count_rel = symbol_record_count(symbol_table_size_rel, symbol_table_entsize_rel);
914+
let target_type_rel = section_type(path, shoff, shentsize, sec_info);
915+
let target_off_rel = section_offset(path, shoff, shentsize, sec_info);
770916
let target_size_rel = section_size(path, shoff, shentsize, sec_info);
771917
let reloc_count_rel = symbol_record_count(sec_size, sec_entsize);
772-
let reloc_status_rel = ingest_relocation_records(
918+
let reloc_status_rel = ingest_relocation_records_rel(
773919
path,
774920
machine,
775921
sec_offset,
@@ -778,6 +924,8 @@ forge ElfFormat {
778924
0,
779925
sec_info,
780926
target_size_rel,
927+
target_type_rel,
928+
target_off_rel,
781929
symbol_count_rel
782930
);
783931
if reloc_status_rel ! 0 {

src/linker_math_tests.ds

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ forge LinkerMathTests {
44
const ERR_OK: UInt32 = 0;
55
const ERR_INVALID_SECTION: UInt32 = 3;
66
const ERR_INVALID_RELOCATION: UInt32 = 6;
7+
const EM_X86_64: UInt16 = 62;
8+
const EM_AARCH64: UInt16 = 183;
9+
const R_X86_64_PC32: UInt32 = 2;
10+
const R_X86_64_32: UInt32 = 10;
11+
const R_X86_64_GLOB_DAT: UInt32 = 6;
12+
const R_AARCH64_PREL32: UInt32 = 261;
713

814
proc K::expect_u32(actual: UInt32, expected: UInt32) -> UInt32 {
915
if actual == expected {
@@ -52,15 +58,32 @@ forge LinkerMathTests {
5258
}
5359

5460
proc K::test_u32_reloc_value_accepts_max() -> UInt32 {
55-
let status = LinkerReloc::K::validate_relocation_value(10, 4294967295);
61+
let status = LinkerReloc::K::validate_relocation_value(R_X86_64_32, EM_X86_64, 4294967295);
5662
return expect_u32(status, ERR_OK);
5763
}
5864

5965
proc K::test_u32_reloc_value_rejects_overflow() -> UInt32 {
60-
let status = LinkerReloc::K::validate_relocation_value(10, 4294967296);
66+
let status = LinkerReloc::K::validate_relocation_value(R_X86_64_32, EM_X86_64, 4294967296);
6167
return expect_u32(status, ERR_INVALID_RELOCATION);
6268
}
6369

70+
proc K::test_x86_64_pc32_accepts_negative_delta() -> UInt32 {
71+
let minus_four = 0 - 4;
72+
let status = LinkerReloc::K::validate_relocation_value(R_X86_64_PC32, EM_X86_64, minus_four);
73+
return expect_u32(status, ERR_OK);
74+
}
75+
76+
proc K::test_x86_64_glob_dat_accepts_64bit_value() -> UInt32 {
77+
let status = LinkerReloc::K::validate_relocation_value(R_X86_64_GLOB_DAT, EM_X86_64, 4294967296);
78+
return expect_u32(status, ERR_OK);
79+
}
80+
81+
proc K::test_aarch64_prel32_accepts_negative_delta() -> UInt32 {
82+
let minus_eight = 0 - 8;
83+
let status = LinkerReloc::K::validate_relocation_value(R_AARCH64_PREL32, EM_AARCH64, minus_eight);
84+
return expect_u32(status, ERR_OK);
85+
}
86+
6487
proc K::run_all_tests() -> UInt32 {
6588
let passed =
6689
test_sections_align_forward_identity()
@@ -70,7 +93,10 @@ forge LinkerMathTests {
7093
+ test_validate_section_span_overflow_rejected()
7194
+ test_pcrel_forward_delta()
7295
+ test_u32_reloc_value_accepts_max()
73-
+ test_u32_reloc_value_rejects_overflow();
96+
+ test_u32_reloc_value_rejects_overflow()
97+
+ test_x86_64_pc32_accepts_negative_delta()
98+
+ test_x86_64_glob_dat_accepts_64bit_value()
99+
+ test_aarch64_prel32_accepts_negative_delta();
74100
return passed;
75101
}
76102
}

0 commit comments

Comments
 (0)