Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ build/
.cache/
tags
*.o
*.out
10 changes: 10 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,13 @@ test(
depends: [bin],
workdir: meson.project_source_root() / 'tests/STB_GLOBAL_NOCONFLICT'
)

test(
'et_rel_fail',
find_program('python3'),
args : [
files('tests/ET_REL_FAIL/tester.py'), bin
],
depends: [bin],
workdir: meson.project_source_root() / 'tests/ET_REL_FAIL'
)
8 changes: 8 additions & 0 deletions src/link.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ bool shared_emachine(uint64_t base, uint64_t input) {
return base == input;
}

bool etype_is_et_rel(Elf_header *header) {
return header->e_type == ET_REL;
}

// checks for stb_global symbol collision between files.
// drains the symtab hashmap and inserts into global hashmap
// collisions between equal values will crash
Expand Down Expand Up @@ -42,6 +46,7 @@ void stb_global_collision(Hashmap **file_symbols, Hashmap **globals, Objdata *fi
// for linking to succeed:
//
// TODO:
// - [ ] all files are relocatable (eheader->e_type is et_rel)
// - [x] same e_machine
// - [x] ensure no global bindings are shared between files
// undefined external references (every symbol needs to have a corresponding address)
Expand All @@ -61,6 +66,9 @@ void validate_objmeta(Objdata *head, Args args) {
if (!shared_emachine(shared_machine, eheader.e_machine))
fatal_error("Different e_machine detected");

if (!etype_is_et_rel(&eheader))
fatal_error("File's e_type is not ET_REL");

// we get a copy of allocated symtab because stb_global calls hashmap_pop
// which modifies the hashmap.
Hashmap **symtab_dup = grab_symbol_table(eheader, sheader, args, path);
Expand Down
7 changes: 7 additions & 0 deletions tests/ET_REL_FAIL/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
clean:
rm *.out

all:
gcc program1.c -o p1.out
gcc program2.c -o p2.out
gcc program3.c -o p3.out
5 changes: 5 additions & 0 deletions tests/ET_REL_FAIL/program1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdio.h>

int main() {
printf("hi meow\n");
}
5 changes: 5 additions & 0 deletions tests/ET_REL_FAIL/program2.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdio.h>

int main() {
printf("hi meow\n");
}
5 changes: 5 additions & 0 deletions tests/ET_REL_FAIL/program3.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <stdio.h>

int main() {
printf("hi meow\n");
}
42 changes: 42 additions & 0 deletions tests/ET_REL_FAIL/tester.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#!/bin/python3

import subprocess
import os
import sys

linker_bin = sys.argv[1]

def test_prom(prom_path: str, bin_path: str, cwd: str):
result = subprocess.run(
[prom_path, bin_path],
capture_output=True, text=True,
cwd=cwd
)
if result.returncode == 0:
print(f"failed to identify {bin_path} is not ET_REL")
print(result.stdout)
print(result.stderr)
exit(1)


def main():
cwd = os.path.dirname(os.path.abspath(__file__))

result = subprocess.run(
["make", "all", "-C", cwd],
capture_output = True, text = True
)

if result.returncode != 0:
print("make failed:", result.stderr)
sys.exit(1)

# checking prom against binaries

for i in range(1,4):
test_prom(linker_bin, f"program{i}.out", cwd)

print("pass")


main()