Skip to content
This repository has been archived by the owner on Mar 4, 2021. It is now read-only.

Commit

Permalink
we can fricking link elfkit with elfkit
Browse files Browse the repository at this point in the history
I should probably hold a speech or something on how fricking painful it
was to get this far

but you know, it's just a linker. right?
  • Loading branch information
aep committed Dec 28, 2017
1 parent 898801e commit 55ce629
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 21 deletions.
4 changes: 4 additions & 0 deletions bin/ld.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ fn main() {
let mut perms = out_file.metadata().unwrap().permissions();
perms.set_mode(0o755);
out_file.set_permissions(perms).unwrap();

}


Expand Down Expand Up @@ -771,6 +772,9 @@ impl SimpleCollector {
if name.len() > 5 && &name[0..6] == b".tdata" {
name = b".tdata".to_vec();
}
if name.len() > 6 && &name[0..7] == b".debug_" {
name = b".dbgFIXME".to_vec();
}

sec.header.flags.remove(types::SectionFlags::GROUP);

Expand Down
44 changes: 29 additions & 15 deletions src/elf.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

use header::Header;
use types;
use error::Error;
Expand Down Expand Up @@ -416,7 +417,7 @@ impl Elf {

self.segments.clear();

//println!("\nstart of Elf::layout segmentation");
trace!("start of Elf::layout segmentation");

let mut current_load_segment_flags = types::SegmentFlags::READABLE;
let mut current_load_segment_poff = 0;
Expand All @@ -429,31 +430,32 @@ impl Elf {

let mut dbg_old_addresses = vec![self.sections[0].header.addr];

//println!(" name \tsize\tpoff\tvoff\tpstart\tvstart\tflags");
trace!(" name \tsize\tpoff\tvoff\tpstart\tvstart\tflags");
for (shndx, sec) in self.sections.iter_mut().enumerate().skip(1) {
dbg_old_addresses.push(sec.header.addr);

//println!(" > {:<10.10}\t{}\t{}\t{}\t{}\t{}\t{:?}",
// String::from_utf8_lossy(&sec.name), sec.header.size, poff, voff,
// current_load_segment_pstart,
// current_load_segment_vstart,
// current_load_segment_flags);
trace!(" > {:<10.10}\t{}\t{}\t{}\t{}\t{}\t{:?}",
String::from_utf8_lossy(&sec.name), sec.header.size, poff, voff,
current_load_segment_pstart,
current_load_segment_vstart,
current_load_segment_flags);

if sec.header.addralign > 0 {
let oa = poff % sec.header.addralign;
if oa != 0 {
poff += sec.header.addralign - oa;
voff += sec.header.addralign - oa;
}
trace!(" ^ realigned for {} to voff 0x{:x}", sec.header.addralign, voff);
}

if sec.header.shtype != types::SectionType::NOBITS {
if poff > voff {
panic!("selfkit: relayout: poff>voff 0x{:x}>0x{:x} in {}.", poff, voff,
panic!("elfkit: relayout: poff>voff 0x{:x}>0x{:x} in {}.", poff, voff,
String::from_utf8_lossy(&sec.name));
}
if (voff - poff) % 0x200000 != 0 {
//println!(" ^ causes segmentation by load alignment");
trace!(" ^ causes segmentation by load alignment");
if sec.header.flags.contains(types::SectionFlags::EXECINSTR) {
current_load_segment_flags.insert(types::SegmentFlags::EXECUTABLE);
}
Expand Down Expand Up @@ -506,9 +508,9 @@ impl Elf {
current_load_segment_vstart = voff;
current_load_segment_flags = types::SegmentFlags::READABLE;
} else {
//println!(" ^ segmentation protection change supressed because it would be empty \
// voff {} <= vstart {}",
// current_load_segment_voff, current_load_segment_vstart);
trace!(" ^ segmentation protection change supressed because it would be empty \
voff {} <= vstart {}",
current_load_segment_voff, current_load_segment_vstart);
}

if sec.header.flags.contains(types::SectionFlags::WRITE) {
Expand All @@ -525,6 +527,7 @@ impl Elf {

sec.header.addr = voff;
voff += sec.header.size;
trace!(" = final addr 0x{:x}", sec.header.addr);

if sec.header.flags.contains(types::SectionFlags::ALLOC) {
current_load_segment_poff = poff;
Expand Down Expand Up @@ -574,7 +577,7 @@ impl Elf {
}
}
if current_load_segment_voff > current_load_segment_vstart {
//println!(" > segmentation caused by end of sections");
trace!(" > segmentation caused by end of sections");
self.segments.push(segment::SegmentHeader {
phtype: types::SegmentType::LOAD,
flags: current_load_segment_flags,
Expand All @@ -593,13 +596,24 @@ impl Elf {
self.header.phoff = self.header.size() as u64;

self.header.ehsize = self.header.size() as u16;
let hoff = (self.header.phnum as u64 * self.header.phentsize as u64) + self.header.ehsize as u64;
let mut hoff = (self.header.phnum as u64 * self.header.phentsize as u64) + self.header.ehsize as u64;

///TODO this is shitty, because we need to replicate all the alignment code
///also most of those sections dont actually need to be moved
for sec in &mut self.sections[1..] {
if sec.header.addralign > 0 {
let oa = hoff % sec.header.addralign;
if oa != 0 {
hoff += sec.header.addralign - oa;
}
}
}
for sec in &mut self.sections[1..] {
sec.header.offset += hoff;
sec.header.addr += hoff;
}


let mut seen_first_load = false;
for seg in self.segments.iter_mut() {
if seg.phtype == types::SegmentType::LOAD && !seen_first_load {
Expand All @@ -624,7 +638,7 @@ impl Elf {
align: 0x8,
});

//println!("done {} segments", self.segments.len());
trace!("done {} segments", self.segments.len());

for i in 0..self.sections.len() {
if self.sections[i].addrlock && self.sections[i].header.addr != dbg_old_addresses[i] {
Expand Down
10 changes: 4 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
#[macro_use]
extern crate bitflags;
#[macro_use] extern crate bitflags;
extern crate byteorder;
#[macro_use]
extern crate enum_primitive_derive;
#[macro_use] extern crate enum_primitive_derive;
extern crate num_traits;
extern crate ordermap;
#[macro_use]
pub mod utils;
#[macro_use] extern crate log;

#[macro_use] pub mod utils;
pub mod dynamic;
pub mod elf;
pub mod error;
Expand Down
Binary file added tests/linker/reloc-21-R_X86_64_DTPOFF32/0-crt1.lo
Binary file not shown.
37 changes: 37 additions & 0 deletions tests/linker/reloc-21-R_X86_64_DTPOFF32/10-main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <stdio.h>
#include <pthread.h>
#include <string.h>


__thread char derp[] = "this is just some random crap to test alingment";

typedef struct {
char x1[32];
char x2[32];
char x3[32];
} blarp;

__thread blarp bla;
__thread char ferp[] = "this is just some random crap to test alingment";


// this will not affect x, because tr gets a thread local copy of x
void *tr(void*_) {
memcpy(&bla.x1, "nope\0", 5);
memcpy(&bla.x2, "nope\0", 5);
}

int main(int argc, char**argv) {
blarp *b = &bla;
strcpy(b->x1, "The quick brown ");
strcpy(b->x2, "fox jumps over the ");
strcpy(b->x3, "lazy dog");

pthread_t t;
pthread_create(&t, 0, &tr, 0);
pthread_join(t, 0);

printf("%s%s%s", bla.x1,bla.x2,bla.x3);
return 42;
}

Binary file not shown.
3 changes: 3 additions & 0 deletions tests/linker/reloc-21-R_X86_64_DTPOFF32/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CFLAGS+=-O0 -ftls-model=local-dynamic
LDFLAGS=--no-relax
include ../common.makefile

0 comments on commit 55ce629

Please sign in to comment.