mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
native: implement elf section types (#15316)
This commit is contained in:
parent
a35356758c
commit
dab8159b56
@ -13,9 +13,12 @@ const (
|
||||
elf_version = 1
|
||||
elf_abiversion = 0
|
||||
|
||||
// elf type
|
||||
elf_type_none = 0
|
||||
elf_type_rel = 1
|
||||
elf_type_exec = 2
|
||||
elf_type_dyn = 3
|
||||
elf_type_core = 4
|
||||
|
||||
elf_amd64 = 0x3e
|
||||
elf_arm64 = 0xb7
|
||||
@ -28,19 +31,46 @@ const (
|
||||
|
||||
elf_header_size = 0x40
|
||||
elf_phentry_size = 0x38
|
||||
elf_shentry_size = 0x40
|
||||
elf_symtab_size = 0x18
|
||||
|
||||
elf_sh_symtab_entsize = 0x18
|
||||
// elf program header type
|
||||
elf_pt_null = 0
|
||||
elf_pt_load = 1
|
||||
elf_pt_dynamic = 2
|
||||
elf_pt_interp = 3
|
||||
elf_pt_note = 4
|
||||
elf_pt_shlib = 5
|
||||
elf_pt_phdr = 6
|
||||
elf_pt_tls = 7
|
||||
|
||||
// alignment of program headers
|
||||
elf_p_align = 0x1000
|
||||
|
||||
// elf section header size
|
||||
elf_shentry_size = 0x40
|
||||
|
||||
// elf section type
|
||||
elf_sht_null = 0x00
|
||||
elf_sht_progbits = 0x01
|
||||
elf_sht_symtab = 0x02
|
||||
elf_sht_strtab = 0x03
|
||||
elf_sht_rela = 0x04
|
||||
elf_sht_hash = 0x05
|
||||
elf_sht_dynamic = 0x06
|
||||
elf_sht_note = 0x07
|
||||
elf_sht_nobits = 0x08
|
||||
elf_sht_rel = 0x09
|
||||
elf_sht_shlib = 0x0a
|
||||
elf_sht_dynsym = 0x0b
|
||||
|
||||
// elf symbol tables
|
||||
elf_symtab_size = 0x18
|
||||
elf_dynamic_size = 0x10
|
||||
elf_rela_size = 0x18
|
||||
elf_rel_size = 0x10
|
||||
elf_sh_symtab_entsize = elf_symtab_size
|
||||
elf_sh_symtab_info = 1
|
||||
elf_sh_symtab_align = 8
|
||||
|
||||
elf_sht_strtab = 3
|
||||
elf_sht_symtab = 2
|
||||
|
||||
elf_pt_load = 1
|
||||
elf_p_align = 0x1000
|
||||
|
||||
// elf symbol bining
|
||||
elf_stb_local = u8(0)
|
||||
elf_stb_global = u8(1)
|
||||
@ -53,6 +83,29 @@ const (
|
||||
|
||||
// elf symbol visibility
|
||||
elf_stv_default = i8(0)
|
||||
|
||||
// elf relocation types
|
||||
elf_r_amd64_none = 0
|
||||
elf_r_amd64_64 = 1
|
||||
elf_r_amd64_pc32 = 2
|
||||
elf_r_amd64_got32 = 3
|
||||
elf_r_amd64_plt32 = 4
|
||||
elf_r_amd64_copy = 5
|
||||
elf_r_amd64_glob_dat = 6
|
||||
elf_r_amd64_jump_slot = 7
|
||||
elf_r_amd64_relative = 8
|
||||
elf_r_amd64_gotpcrel = 9
|
||||
elf_r_amd64_32 = 10
|
||||
elf_r_amd64_32s = 11
|
||||
elf_r_amd64_16 = 12
|
||||
elf_r_amd64_pc16 = 13
|
||||
elf_r_amd64_8 = 14
|
||||
elf_r_amd64_pc8 = 15
|
||||
elf_r_amd64_pc64 = 24
|
||||
elf_r_amd64_gotoff64 = 25
|
||||
elf_r_amd64_gotpc32 = 26
|
||||
elf_r_amd64_size32 = 32
|
||||
elf_r_amd64_size64 = 33
|
||||
)
|
||||
|
||||
const (
|
||||
@ -85,7 +138,7 @@ fn (mut p ProgramHeader) set_addr(addr i64) {
|
||||
p.paddr = addr
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_program_header64(p ProgramHeader) {
|
||||
fn (mut g Gen) gen_program_header(p ProgramHeader) {
|
||||
g.write32(p.typ) // p_type
|
||||
g.println('; p_type')
|
||||
g.write32(p.flags) // p_flags
|
||||
@ -130,19 +183,19 @@ mut:
|
||||
entsize i64 // Section entry size.
|
||||
}
|
||||
|
||||
struct SymbolTable {
|
||||
struct SymbolTableSection {
|
||||
str_name string // string name (not generated)
|
||||
mut:
|
||||
name int // Index to name in .strtab.
|
||||
info i8 // symbol type and binding attribute.
|
||||
other i8 // Symbol visibility.
|
||||
shndx i16 // Related section header table index.
|
||||
value i64 // value of the associated symbol
|
||||
size i64 // Symbol size
|
||||
value i64 // value of the associated symbol.
|
||||
size i64 // Symbol size.
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_symbol_table(str_name string, info u8, bind u8, other i8, value i64, size i64) SymbolTable {
|
||||
return SymbolTable{
|
||||
fn (mut g Gen) create_symbol_table_section(str_name string, info u8, bind u8, other i8, value i64, size i64) SymbolTableSection {
|
||||
return SymbolTableSection{
|
||||
str_name: str_name
|
||||
info: i8(info | bind << 4)
|
||||
other: other
|
||||
@ -151,16 +204,127 @@ fn (mut g Gen) create_symbol_table(str_name string, info u8, bind u8, other i8,
|
||||
}
|
||||
}
|
||||
|
||||
struct StringTable {
|
||||
struct StringTableSection {
|
||||
mut:
|
||||
strings []string
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_string_table(strings []string) StringTable {
|
||||
return StringTable{strings}
|
||||
fn (mut g Gen) create_string_table_section(strings []string) StringTableSection {
|
||||
return StringTableSection{strings}
|
||||
}
|
||||
|
||||
type SectionData = StringTable | []SymbolTable
|
||||
struct ProgBitsSection {
|
||||
mut:
|
||||
bytes []u8 // Bytes of information defined by the program.
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_progbits_section(bytes []u8) ProgBitsSection {
|
||||
return ProgBitsSection{bytes}
|
||||
}
|
||||
|
||||
struct RelASection {
|
||||
mut:
|
||||
offset i64 // Location at which to apply the relocation action.
|
||||
info i64 // Symbol table index and type of relocation to apply.
|
||||
addend i64 // Constant addent for computing the value of the relocation field.
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_rela_section(offset i64, sym u32, typ u32, addend i64) RelASection {
|
||||
return RelASection{
|
||||
offset: offset
|
||||
info: i64((u64(sym) << 32) + typ)
|
||||
addend: addend
|
||||
}
|
||||
}
|
||||
|
||||
struct HashSection {
|
||||
// TODO
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_hash_section() HashSection {
|
||||
return HashSection{}
|
||||
}
|
||||
|
||||
struct DynamicSection {
|
||||
mut:
|
||||
tag i64 // Type of the dynamic Section.
|
||||
un i64 // Consists of d_val and d_ptr, represents program virtual addresses.
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_dynamic_section(tag i64, val i64) DynamicSection {
|
||||
return DynamicSection{tag, val}
|
||||
}
|
||||
|
||||
struct NoteSection {
|
||||
mut:
|
||||
namesz int // Length of the name field in bytes.
|
||||
descsz int // Length of the descriptor field in bytes.
|
||||
typ int // Type of the node
|
||||
|
||||
name []u8 // Name string of the note.
|
||||
desc []u8 // Descripition string of the node, must be aligned by 4 bytes
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_note_section(typ int, name string, desc string) NoteSection {
|
||||
return NoteSection{
|
||||
namesz: name.len
|
||||
descsz: desc.len
|
||||
typ: typ
|
||||
name: name.bytes()
|
||||
desc: desc.bytes()
|
||||
}
|
||||
}
|
||||
|
||||
struct NoBitsSection {
|
||||
// The NoBits section does not occupy any bytes in the file
|
||||
}
|
||||
|
||||
fn (mut g Gen) chreate_nobits_section() NoBitsSection {
|
||||
return NoBitsSection{}
|
||||
}
|
||||
|
||||
struct RelSection {
|
||||
mut:
|
||||
offset i64 // Location at which to apply the relocation action.
|
||||
info i64 // Symbol table index and type of relocation to apply.
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_rel_section(offset i64, sym u32, typ u32) RelSection {
|
||||
return RelSection{
|
||||
offset: offset
|
||||
info: i64((u64(sym) << 32) + typ)
|
||||
}
|
||||
}
|
||||
|
||||
struct ShLibSection {
|
||||
mut:
|
||||
data []u8 // Reserved bytes with unspecified semantics
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_shlib_section(data []u8) ShLibSection {
|
||||
return ShLibSection{data}
|
||||
}
|
||||
|
||||
struct DynSymSection {
|
||||
mut:
|
||||
symbols []SymbolTableSection
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_dynsym_section(symbols []SymbolTableSection) DynSymSection {
|
||||
return DynSymSection{symbols}
|
||||
}
|
||||
|
||||
type SectionData = DynSymSection
|
||||
| HashSection
|
||||
| NoBitsSection
|
||||
| NoteSection
|
||||
| ProgBitsSection
|
||||
| RelASection
|
||||
| RelSection
|
||||
| ShLibSection
|
||||
| StringTableSection
|
||||
| []DynamicSection
|
||||
| []SymbolTableSection
|
||||
|
||||
struct Section {
|
||||
name string
|
||||
@ -196,13 +360,13 @@ fn (mut g Gen) create_shstrtab(mut sections []Section) {
|
||||
names[sections.len] = '.shstrtab'
|
||||
|
||||
mut shstrtab := g.create_section(names[sections.len], native.elf_sht_strtab, 0, 0,
|
||||
1, 0, g.create_string_table(names))
|
||||
1, 0, g.create_string_table_section(names))
|
||||
shstrtab.header.name = offset
|
||||
|
||||
sections << shstrtab
|
||||
}
|
||||
|
||||
fn (mut g Gen) create_symtab(mut sections []Section, mut table []SymbolTable) {
|
||||
fn (mut g Gen) create_symtab(mut sections []Section, mut table []SymbolTableSection) {
|
||||
mut names := []string{len: table.len}
|
||||
mut offset := 1
|
||||
|
||||
@ -215,7 +379,7 @@ fn (mut g Gen) create_symtab(mut sections []Section, mut table []SymbolTable) {
|
||||
offset += entry.str_name.len + 1
|
||||
}
|
||||
|
||||
sections << g.create_section('.strtab', native.elf_sht_strtab, 0, 0, 1, 0, g.create_string_table(names))
|
||||
sections << g.create_section('.strtab', native.elf_sht_strtab, 0, 0, 1, 0, g.create_string_table_section(names))
|
||||
|
||||
sections << // index of .strtab
|
||||
g.create_section('.symtab', native.elf_sht_symtab, sections.len - 1, native.elf_sh_symtab_info,
|
||||
@ -231,7 +395,7 @@ fn (mut g Gen) find_section_header(name string, sections []Section) int {
|
||||
return 0
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_section_header64(mut sh SectionHeader) {
|
||||
fn (mut g Gen) gen_section_header(mut sh SectionHeader) {
|
||||
sh_offset := g.pos()
|
||||
|
||||
g.write32(sh.name) // sh_name
|
||||
@ -263,11 +427,30 @@ fn (mut g Gen) gen_section_header64(mut sh SectionHeader) {
|
||||
|
||||
fn (mut g Gen) gen_sections(mut sections []Section) {
|
||||
for mut section in sections {
|
||||
g.gen_section_header64(mut section.header)
|
||||
g.gen_section_header(mut section.header)
|
||||
g.println('; ^^^ section header (64) "$section.name"')
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_symtab_data(section Section, data []SymbolTableSection) {
|
||||
for symbol in data {
|
||||
if symbol.str_name == '_start' {
|
||||
g.start_symbol_addr = g.pos()
|
||||
}
|
||||
|
||||
g.write32(symbol.name)
|
||||
g.write8(symbol.info)
|
||||
g.write8(symbol.other)
|
||||
g.write16(symbol.shndx)
|
||||
g.write64(symbol.value)
|
||||
g.write64(symbol.size)
|
||||
g.println('; SHT_SYMTAB $symbol.str_name')
|
||||
}
|
||||
|
||||
size := native.elf_symtab_size * data.len
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
|
||||
fn (mut g Gen) gen_section_data(sections []Section) {
|
||||
for section in sections {
|
||||
data := section.data
|
||||
@ -276,7 +459,7 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
||||
g.write64_at(section.header.offset + 24, i64(g.pos()))
|
||||
|
||||
match data {
|
||||
StringTable {
|
||||
StringTableSection {
|
||||
start := g.pos()
|
||||
|
||||
g.write8(0) // null-prefixed
|
||||
@ -290,24 +473,79 @@ fn (mut g Gen) gen_section_data(sections []Section) {
|
||||
size := g.pos() - start
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
[]SymbolTable {
|
||||
for symbol in data {
|
||||
if symbol.str_name == '_start' {
|
||||
g.start_symbol_addr = g.pos()
|
||||
[]SymbolTableSection {
|
||||
g.gen_symtab_data(section, data)
|
||||
}
|
||||
ProgBitsSection {
|
||||
start := g.pos()
|
||||
|
||||
g.write32(symbol.name)
|
||||
g.write8(symbol.info)
|
||||
g.write8(symbol.other)
|
||||
g.write16(symbol.shndx)
|
||||
g.write64(symbol.value)
|
||||
g.write64(symbol.size)
|
||||
g.println('; $symbol')
|
||||
}
|
||||
g.write(data.bytes)
|
||||
g.println('; SHT_PROGBITS Section')
|
||||
|
||||
size := native.elf_symtab_size * data.len
|
||||
size := g.pos() - start
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
RelASection {
|
||||
g.write64(data.offset)
|
||||
g.write64(data.info)
|
||||
g.write64(data.addend)
|
||||
g.println('; SHT_RELA ($data.offset, $data.info, $data.addend)')
|
||||
|
||||
size := native.elf_rela_size
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
HashSection {
|
||||
// TODO
|
||||
g.n_error('ELF Section `SHT_HASH` not implemented yet')
|
||||
}
|
||||
[]DynamicSection {
|
||||
for dyn in data {
|
||||
g.write64(dyn.tag)
|
||||
g.write64(dyn.un)
|
||||
g.println('; SHT_DYNAMIC ($dyn.tag, $dyn.un)')
|
||||
}
|
||||
|
||||
size := native.elf_dynamic_size * data.len
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
NoteSection {
|
||||
start := g.pos()
|
||||
|
||||
g.write32(data.namesz)
|
||||
g.write32(data.descsz)
|
||||
g.write32(data.typ)
|
||||
g.write(data.name)
|
||||
|
||||
for _ in 0 .. ((g.pos() % 4) + 1) {
|
||||
g.write8(0) // align by 4 bytes + null terminator
|
||||
}
|
||||
|
||||
g.write(data.desc)
|
||||
g.write8(0)
|
||||
|
||||
size := g.pos() - start
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
NoBitsSection {
|
||||
// Nothing to do
|
||||
}
|
||||
RelSection {
|
||||
g.write64(data.offset)
|
||||
g.write64(data.info)
|
||||
g.println('; SHT_REL ($data.offset, $data.info)')
|
||||
|
||||
size := native.elf_rel_size
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
ShLibSection {
|
||||
g.write(data.data)
|
||||
|
||||
size := data.data.len
|
||||
g.write64_at(section.header.offset + 32, i64(size))
|
||||
}
|
||||
DynSymSection {
|
||||
g.gen_symtab_data(section, data.symbols)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -343,21 +581,26 @@ mut:
|
||||
pub fn (mut g Gen) generate_elf_header() {
|
||||
elf_type := native.elf_type_exec // PIE (use _exec for non-relocatable executables)
|
||||
|
||||
// generate program headers
|
||||
mut program_headers := []ProgramHeader{}
|
||||
program_headers << g.create_program_header(native.elf_pt_load, 5, native.elf_p_align)
|
||||
|
||||
// generate sections
|
||||
mut sections := [
|
||||
Section{}, // null section as first section
|
||||
]
|
||||
|
||||
mut symbols := [
|
||||
SymbolTable{}, // first is null
|
||||
g.create_symbol_table('_start', native.elf_stt_notype, native.elf_stb_global,
|
||||
native.elf_stv_default, 0, 0),
|
||||
SymbolTableSection{}, // first is null
|
||||
g.create_symbol_table_section('_start', native.elf_stt_notype, native.elf_stb_global,
|
||||
native.elf_stv_default, 0, 0), // _start label points to entry point address
|
||||
]
|
||||
|
||||
g.create_symtab(mut sections, mut symbols)
|
||||
g.create_symtab(mut sections, mut symbols) // create the .symtab section
|
||||
g.create_shstrtab(mut sections) // create the .shstrtab section (this must be the last section!)
|
||||
|
||||
// write elf header
|
||||
g.buf << '\x7fELF'.bytes()
|
||||
g.println('; elf header (magic)')
|
||||
g.println('; \\x7fELF')
|
||||
g.buf << native.elf_class64
|
||||
g.buf << native.elf_data_le
|
||||
g.buf << native.elf_version
|
||||
@ -375,20 +618,20 @@ pub fn (mut g Gen) generate_elf_header() {
|
||||
e_entry_addr := g.pos()
|
||||
g.write64(0) // e_entry (temp value)
|
||||
g.write64(native.elf_header_size) // e_phoff
|
||||
g.write64(native.elf_header_size + native.elf_phentry_size) // e_shoff
|
||||
g.write64(native.elf_header_size + native.elf_phentry_size * program_headers.len) // e_shoff
|
||||
g.write32(0) // e_flags
|
||||
g.write16(native.elf_header_size)
|
||||
g.write16(native.elf_phentry_size)
|
||||
g.write16(1) // e_phnum
|
||||
g.write16(program_headers.len) // e_phnum
|
||||
g.write16(native.elf_shentry_size) // e_shentsize
|
||||
// e_shnum := g.buf.len
|
||||
g.write16(sections.len) // e_shnum (number of sections)
|
||||
g.write16(g.find_section_header('.shstrtab', sections)) // e_shstrndx
|
||||
|
||||
// Elf64_Phdr
|
||||
// Main program header
|
||||
phdr := g.create_program_header(native.elf_pt_load, 5, native.elf_p_align)
|
||||
g.gen_program_header64(phdr)
|
||||
// write program headers
|
||||
for header in program_headers {
|
||||
g.gen_program_header(header)
|
||||
}
|
||||
|
||||
// write section headers
|
||||
g.gen_sections(mut sections)
|
||||
@ -403,7 +646,9 @@ pub fn (mut g Gen) generate_elf_header() {
|
||||
|
||||
g.code_start_pos = g.pos()
|
||||
g.debug_pos = int(g.pos())
|
||||
if elf_type == native.elf_type_exec {
|
||||
g.write64_at(e_entry_addr, g.code_start_pos + native.segment_start)
|
||||
}
|
||||
if g.start_symbol_addr > 0 {
|
||||
g.write64_at(g.start_symbol_addr + native.elf_symtab_size - 16, g.code_start_pos +
|
||||
native.segment_start)
|
||||
|
Loading…
Reference in New Issue
Block a user