diff --git a/bootstrap/lib.h b/bootstrap/lib.h index 5a0dc0a..3c96da6 100644 --- a/bootstrap/lib.h +++ b/bootstrap/lib.h @@ -3203,6 +3203,168 @@ fn MD5Result md5_end(MD5Context* context) return result; } +// https://github.com/jasinb/sha1.git +STRUCT(Sha1Digest) +{ + u32 digest[5]; +}; + +// static uint32_t rotl32(uint32_t x, int b) +// { +// return (x << b) | (x >> (32-b)); +// } +// +// switch endianness +fn u32 sha1_get32(u8* p) +{ + return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]; +} + +fn u32 sha1_f(int t, u32 b, u32 c, u32 d) +{ + assert(0 <= t && t < 80); + + if (t < 20) + { + return (b & c) | ((~b) & d); + } + else if (t < 40) + { + return b ^ c ^ d; + } + else if (t < 60) + { + return (b & c) | (b & d) | (c & d); + } + else + //if (t < 80) + { + return b ^ c ^ d; + } +} + +STRUCT(Sha1Context) +{ + u8 block[64]; + u32 h[5]; + u64 bytes; + u32 cur; +}; + +fn void sha1_reset(Sha1Context* ctx) +{ + ctx->h[0] = 0x67452301; + ctx->h[1] = 0xefcdab89; + ctx->h[2] = 0x98badcfe; + ctx->h[3] = 0x10325476; + ctx->h[4] = 0xc3d2e1f0; + ctx->bytes = 0; + ctx->cur = 0; +} + +fn void sha1_process_block(Sha1Context* ctx) +{ + global const u32 k[4] = + { + 0x5A827999, + 0x6ED9EBA1, + 0x8F1BBCDC, + 0xCA62C1D6 + }; + + u32 w[16]; + u32 a = ctx->h[0]; + u32 b = ctx->h[1]; + u32 c = ctx->h[2]; + u32 d = ctx->h[3]; + u32 e = ctx->h[4]; + u32 t; + + for (t = 0; t < 16; t++) + w[t] = sha1_get32((u8*)(&((uint32_t*)ctx->block)[t])); + + for (t = 0; t < 80; t++) + { + auto s = t & 0xf; + u32 temp; + if (t >= 16) + w[s] = rotate_left_u32(w[(s + 13) & 0xf] ^ w[(s + 8) & 0xf] ^ w[(s + 2) & 0xf] ^ w[s], 1); + + temp = rotate_left_u32(a, 5) + sha1_f(t, b,c,d) + e + w[s] + k[t/20]; + + e = d; d = c; c = rotate_left_u32(b, 30); b = a; a = temp; + } + + ctx->h[0] += a; + ctx->h[1] += b; + ctx->h[2] += c; + ctx->h[3] += d; + ctx->h[4] += e; +} + +fn void sha1_write(Sha1Context* ctx, String bytes) +{ + auto length = bytes.length; + ctx->bytes += length; + + const uint8_t* src = bytes.pointer; + while (length--) + { + // TODO: could optimize the first and last few bytes, and then copy + // 128 bit blocks with SIMD in between + ctx->block[ctx->cur++] = *src++; + if (ctx->cur == 64) + { + sha1_process_block(ctx); + ctx->cur = 0; + } + } +} + +fn Sha1Digest sha1_get_digest(Sha1Context* ctx) +{ + // append separator + ctx->block[ctx->cur++] = 0x80; + if (ctx->cur > 56) + { + // no space in block for the 64-bit message length, flush + memset(&ctx->block[ctx->cur], 0, 64 - ctx->cur); + sha1_process_block(ctx); + ctx->cur = 0; + } + + memset(&ctx->block[ctx->cur], 0, 56 - ctx->cur); + uint64_t bits = ctx->bytes * 8; + + // TODO a few instructions could be shaven + ctx->block[56] = (uint8_t)(bits >> 56 & 0xff); + ctx->block[57] = (uint8_t)(bits >> 48 & 0xff); + ctx->block[58] = (uint8_t)(bits >> 40 & 0xff); + ctx->block[59] = (uint8_t)(bits >> 32 & 0xff); + ctx->block[60] = (uint8_t)(bits >> 24 & 0xff); + ctx->block[61] = (uint8_t)(bits >> 16 & 0xff); + ctx->block[62] = (uint8_t)(bits >> 8 & 0xff); + ctx->block[63] = (uint8_t)(bits >> 0 & 0xff); + sha1_process_block(ctx); + + { + Sha1Digest ret; + int i; + for (i = 0; i < 5; i++) + ret.digest[i] = sha1_get32((u8*)&ctx->h[i]); + sha1_reset(ctx); + return ret; + } +} + +fn Sha1Digest sha1_compute(String bytes) +{ + Sha1Context ctx; + sha1_reset(&ctx); + sha1_write(&ctx, bytes); + return sha1_get_digest(&ctx); +} + fn void entry_point(int argc, char* argv[], char* envp[]); #if LINK_LIBC diff --git a/bootstrap/main.c b/bootstrap/main.c index 01701de..5949efb 100644 --- a/bootstrap/main.c +++ b/bootstrap/main.c @@ -8029,6 +8029,8 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr u32 gnu_property_offset = 0; u32 gnu_property_size = 0; u32 gnu_property_alignment = 0; + auto gnu_string = strlit("GNU"); + auto gnu_string_size = gnu_string.length + 1; { // .note.gnu.property // Section #2 @@ -8040,8 +8042,6 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr gnu_property_offset = offset; auto gnu_property_section_name = elf_get_section_name(builder, strlit(".note.gnu.property")); - auto gnu_string = strlit("GNU"); - auto gnu_string_size = gnu_string.length + 1; auto* ptr = vb_add_struct(&builder->file, ELFNoteHeader); *ptr = (ELFNoteHeader) { @@ -8074,61 +8074,59 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr }; } - u32 gnu_build_id_offset = 0; - u32 gnu_build_id_alignment = 0; - { - // .note.gnu.build-id - // Section #3 - auto* section_header = vb_add(&builder->section_headers, 1); - u64 alignment = 4; - gnu_build_id_alignment = alignment; - auto name = elf_get_section_name(builder, strlit(".note.gnu.build-id")); - vb_align(&builder->file, alignment); - auto offset = builder->file.length; - gnu_build_id_offset = offset; - - auto gnu_string = strlit("GNU"); - auto gnu_string_size = gnu_string.length + 1; - - u8 blob[] = { 0xF0, 0xDE, 0x30, 0xDB, 0x5A, 0x9F, 0xE2, 0x4E, 0x0A, 0xCF, 0x93, 0xA4, 0x4C, 0x11, 0x60, 0xB5, 0x0C, 0xD9, 0xAF, 0x50, }; - static_assert(sizeof(blob) == 20); - - *(vb_add_struct(&builder->file, ELFNoteHeader)) = (ELFNoteHeader) - { - .name_size = gnu_string_size, - .descriptor_size = sizeof(blob), - .type = NT_GNU_BUILD_ID, - }; - memcpy(vb_add(&builder->file, gnu_string_size), gnu_string.pointer, gnu_string_size); - memcpy(vb_add(&builder->file, sizeof(blob)), blob, sizeof(blob)); - - auto size = builder->file.length - offset; - - *section_header = (ELFSectionHeader) - { - .name_offset = name, - .type = ELF_SECTION_NOTE, - .flags = { - .alloc = 1, - }, - .address = offset, - .offset = offset, - .size = size, - .link = 0, - .info = 0, - .alignment = alignment, - .entry_size = 0, - }; - } - + // u32 gnu_build_id_offset = 0; + // u32 gnu_build_id_alignment = 0; + // ELFNoteHeader* gnu_build_id_header = 0; + // u8* gnu_build_id_string = 0; + // u8* gnu_build_id_blob = 0; + // u32 gnu_build_id_blob_size = 20; + // { + // // .note.gnu.build-id + // // Section #3 + // auto* section_header = vb_add(&builder->section_headers, 1); + // u64 alignment = 4; + // gnu_build_id_alignment = alignment; + // auto name = elf_get_section_name(builder, strlit(".note.gnu.build-id")); + // vb_align(&builder->file, alignment); + // auto offset = builder->file.length; + // gnu_build_id_offset = offset; + // + // gnu_build_id_header = vb_add_struct(&builder->file, ELFNoteHeader); + // gnu_build_id_string = vb_add(&builder->file, gnu_string_size); + // gnu_build_id_blob = vb_add(&builder->file, gnu_build_id_blob_size); + // + // auto size = builder->file.length - offset; + // memset(builder->file.pointer + offset, 0, size); + // + // *section_header = (ELFSectionHeader) + // { + // .name_offset = name, + // .type = ELF_SECTION_NOTE, + // .flags = { + // .alloc = 1, + // }, + // .address = offset, + // .offset = offset, + // .size = size, + // .link = 0, + // .info = 0, + // .alignment = alignment, + // .entry_size = 0, + // }; + // } + + u32 gnu_build_id_abi_note_offset = 0; + u32 gnu_build_id_abi_alignment = 0; { // .note.ABI-tag // Section #4 auto* section_header = vb_add(&builder->section_headers, 1); u64 alignment = 4; + gnu_build_id_abi_alignment = alignment; vb_align(&builder->file, alignment); auto offset = builder->file.length; + gnu_build_id_abi_note_offset = offset; auto name = elf_get_section_name(builder, strlit(".note.ABI-tag")); @@ -8168,7 +8166,7 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr }; } - auto gnu_build_id_abi_note_size = builder->file.length - gnu_build_id_offset; + auto gnu_build_id_abi_note_size = builder->file.length - gnu_build_id_abi_note_offset; u16 preliminar_section_count = builder->section_headers.length + 1; auto dynamic_symbol_table_index = preliminar_section_count; @@ -8491,7 +8489,6 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr // Add read-only program segment { auto offset = builder->file.length; - assert(offset == 1496); *vb_add(&builder->program_headers, 1) = (ElfProgramHeader) { @@ -9240,12 +9237,12 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr *vb_add(&builder->program_headers, 1) = (ElfProgramHeader) { .type = PT_NOTE, .flags = {.readable = 1}, - .offset = gnu_build_id_offset, - .virtual_address = gnu_build_id_offset, - .physical_address = gnu_build_id_offset, + .offset = gnu_build_id_abi_note_offset, + .virtual_address = gnu_build_id_abi_note_offset, + .physical_address = gnu_build_id_abi_note_offset, .file_size = gnu_build_id_abi_note_size, .memory_size = gnu_build_id_abi_note_size, - .alignment = gnu_build_id_alignment, + .alignment = gnu_build_id_abi_alignment, }; *vb_add(&builder->program_headers, 1) = (ElfProgramHeader) { @@ -9794,7 +9791,7 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr u8 directory_index; MD5Result hash; }; - MD5Result md5_hash = { { 0x05, 0xAB, 0x89, 0xF5, 0x48, 0x1B, 0xC9, 0xF2, 0xD0, 0x37, 0xE7, 0x88, 0x66, 0x41, 0xE9, 0x19 } }; + MD5Result md5_hash = { { 0x05, 0xAB, 0x89, 0xF5, 0x48, 0x1B, 0xC9, 0xF2, 0xD0, 0x37, 0xE7, 0x88, 0x66, 0x41, 0xE9, 0x19 } }; #if 0 String dummy_file = file_read(thread->arena, strlit("/home/david/minimal/main.c")); auto md5 = md5_init(); @@ -10371,6 +10368,25 @@ may_be_unused fn void write_elf(Thread* thread, const ObjectOptions* const restr assert(relocation_index == expected_relocation_count); + // // .note.gnu.build-id + // { + // u8 blob[] = { 0xF0, 0xDE, 0x30, 0xDB, 0x5A, 0x9F, 0xE2, 0x4E, 0x0A, 0xCF, 0x93, 0xA4, 0x4C, 0x11, 0x60, 0xB5, 0x0C, 0xD9, 0xAF, 0x50, }; + // + // // *gnu_build_id_header = (ELFNoteHeader) + // // { + // // .name_size = gnu_string_size, + // // .descriptor_size = sizeof(blob), + // // .type = NT_GNU_BUILD_ID, + // // }; + // // memcpy(gnu_build_id_string, gnu_string.pointer, gnu_string_size); + // + // auto f = file_read(thread->arena, strlit("/home/david/minimal/main")); + // String exe = { builder->file.pointer, builder->file.length }; + // auto sha1 = sha1_compute(exe); + // assert(sizeof(blob) == gnu_build_id_blob_size); + // // memcpy(gnu_build_id_blob, blob, sizeof(blob)); + // } + // Check if the file matches // {