summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-11-04 21:57:57 -0400
committerpommicket <pommicket@gmail.com>2022-11-04 21:57:57 -0400
commitbd54f4f57a56de5b2d8b80949acfd499a62a0bbf (patch)
tree2147654ab748b7fe92571cd6296908291d24c3b8
parentaa6a7044fbaeb1371f9ac8dd1f7ae5834002aafc (diff)
printf now working for tcc (not gcc yet because of strings)
-rw-r--r--src/main.rs55
-rw-r--r--test.c12
2 files changed, 36 insertions, 31 deletions
diff --git a/src/main.rs b/src/main.rs
index c36df98..4717932 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -369,7 +369,7 @@ struct Executable {
interp: Vec<u8>,
load_addr: u64,
bss: Option<(u64, u64)>,
- relocations: Vec<Relocation>,
+ relocations: Vec<(Relocation, u64)>,
strtab: Vec<u8>,
symbol_strtab_offsets: HashMap<SymbolName, u64>,
lib_strtab_offsets: Vec<u64>,
@@ -410,7 +410,7 @@ impl Executable {
self.lib_strtab_offsets.push(s);
}
- pub fn add_relocation(&mut self, symbol_names: &SymbolNames, rel: &Relocation) {
+ pub fn add_relocation(&mut self, symbol_names: &SymbolNames, rel: &Relocation, addr: u64) {
let name = rel.sym;
if self.symbol_strtab_offsets.get(&name).is_none() {
@@ -418,7 +418,7 @@ impl Executable {
let offset = self.add_string(s);
self.symbol_strtab_offsets.insert(name, offset);
}
- self.relocations.push(rel.clone());
+ self.relocations.push((rel.clone(), addr));
}
fn segment_count(&self) -> u16 {
@@ -450,7 +450,6 @@ impl Executable {
pub fn write<T: Write + Seek>(&self, data: &[u8], out: &mut T) -> LinkResult<()> {
let load_addr = self.load_addr as u32;
- let data_addr: u32 = self.data_addr() as u32;
// start by writing data.
out.seek(io::SeekFrom::Start(self.data_offset()))?;
@@ -488,11 +487,10 @@ impl Executable {
}
// now reltab
let reltab_offset = out.stream_position()?;
- for reloc in self.relocations.iter() {
+ for (reloc, addr) in self.relocations.iter() {
let index = *symbols.get(&reloc.sym).unwrap();
- println!("{:x}", index << 8 | u32::from(reloc.r#type.to_x86_u8()));
let rel = elf::Rel32 {
- offset: load_addr, // @TODO
+ offset: *addr as u32,
info: index << 8 | u32::from(reloc.r#type.to_x86_u8()),
};
out.write_all(&rel.to_bytes())?;
@@ -502,15 +500,15 @@ impl Executable {
let hashtab_offset = out.stream_position()?;
// put everything in a single bucket
let nsymbols = symbols.len() as u32;
- out.write_all(&u32::to_le_bytes(1))?;
- out.write_all(&u32::to_le_bytes(nsymbols))?;
+ out.write_all(&u32::to_le_bytes(1))?; // nbucket
+ out.write_all(&u32::to_le_bytes(nsymbols + 1))?; // nchain
out.write_all(&u32::to_le_bytes(0))?; // bucket begins at 0
// chain 1 -> 2 -> 3 -> ... -> n -> 0
for i in 1..nsymbols {
out.write_all(&u32::to_le_bytes(i))?;
}
- // @OPTIMIZE: can be removed with potentially disastrous results if
- // a symbol is not found.
+ out.write_all(&u32::to_le_bytes(0))?;
+ // i don't know why this needs to be here.
out.write_all(&u32::to_le_bytes(0))?;
@@ -546,13 +544,13 @@ impl Executable {
let mut ehdr = elf::Ehdr32::default();
ehdr.phnum = self.segment_count();
ehdr.phoff = elf::Ehdr32::size_of() as u32;
- ehdr.entry = self.data_offset().try_into().map_err(|_| LinkError::TooLarge)?;
+ ehdr.entry = self.data_addr().try_into().map_err(|_| LinkError::TooLarge)?;
out.write_all(&ehdr.to_bytes())?;
let phdr_data = elf::Phdr32 {
flags: elf::PF_R | elf::PF_W | elf::PF_X, // read, write, execute
offset: 0,
- vaddr: data_addr,
+ vaddr: load_addr,
filesz: file_size,
memsz: file_size,
..Default::default()
@@ -1016,12 +1014,18 @@ impl Linker {
},
}
}
+
+ fn get_rel_apply_data_offset(&self, rel: &Relocation) -> Option<u64> {
+ let apply_symbol = rel.r#where.0;
+ let r = self.symbol_data_offsets.get(&apply_symbol)?;
+ Some(*r + rel.r#where.1)
+ }
- fn apply_relocation(&mut self, rel: Relocation, data: &mut [u8]) -> Result<(), LinkError> {
+ fn apply_relocation(&mut self, rel: &Relocation, data: &mut [u8]) -> Result<(), LinkError> {
let apply_symbol = rel.r#where.0;
- let apply_offset = rel.r#where.1 + match self.symbol_data_offsets.get(&apply_symbol) {
- None => return Ok(()), // this relocation isn't in a section we care about
- Some(a) => *a,
+ let apply_offset = match self.get_rel_apply_data_offset(&rel) {
+ Some(data_offset) => data_offset,
+ None => return Ok(()) // this relocation isn't in a data section so there's nothing we can do about it
};
let apply_addr = apply_offset + self.data_addr;
@@ -1136,12 +1140,6 @@ impl Linker {
exec.set_interp("/lib/ld-linux.so.2");
exec.add_lib("libc.so.6");
- for rel in relocations.iter() {
- let mut _data = [0; MAX_REL_SIZE];
- if self.get_relocation_data(rel, 0, &mut _data)?.is_none() {
- exec.add_relocation(&self.symbol_names, rel);
- }
- }
self.data_addr = exec.data_addr();
@@ -1158,8 +1156,17 @@ impl Linker {
let mut data = vec![];
self.add_data_for_symbol(&mut data, &symbol_graph, entry_id)?;
+ for rel in relocations.iter() {
+ self.apply_relocation(&rel, &mut data)?;
+ }
+
for rel in relocations {
- self.apply_relocation(rel, &mut data)?;
+ let mut _data = [0; MAX_REL_SIZE];
+ if self.get_relocation_data(&rel, 0, &mut _data)?.is_none() {
+ if let Some(data_offset) = self.get_rel_apply_data_offset(&rel) {
+ exec.add_relocation(&self.symbol_names, &rel, self.data_addr + data_offset);
+ }
+ }
}
exec.write(&data, out)
diff --git a/test.c b/test.c
index e2db834..f34d4e2 100644
--- a/test.c
+++ b/test.c
@@ -1,12 +1,10 @@
#include <stdio.h>
+#include <stdlib.h>
+
int x;
void main() {
- x = 123;
- printf("hi");
- __asm__ ("movl $1, %%eax\n"
- "movl %0, %%ebx\n"
- "int $0x80\n"
- :
- : "r" (x) : "ebx", "eax");
+ puts("HellO");
+ printf("hello\n");
+ _exit(123);
}