diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-06-11 12:58:23 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-06-11 12:58:23 +0200 |
commit | 0158fc479e3be59f1e2e8bfea4d0021e135a589e (patch) | |
tree | 2a23101b6e7894253206c9561ee4776b45f1dadc | |
parent | b8ab04e26e8d1352e5a6cbd51e640c7d799e2eb3 (diff) | |
download | bxgen-0158fc479e3be59f1e2e8bfea4d0021e135a589e.zip |
parsing ar library
-rwxr-xr-x | bxgen.c | 193 |
1 files changed, 184 insertions, 9 deletions
@@ -2,6 +2,7 @@ SRC=${0##*/} BIN=${SRC%.*} gcc \ + -Wno-old-style-declaration \ -Wno-missing-field-initializers -Wno-missing-braces \ -Wall -Wextra -Werror -pedantic \ -O0 -fsanitize=undefined,address,leak -mshstk \ @@ -181,9 +182,14 @@ enum { IO_OPEN = 0, IO_CLOSE, + IO_SEEK, IO_READ, IO_WRITE, IO_CHMOD_EXE, + + IO_SEEK_CURSOR = 0, + IO_SEEK_BEGIN, + IO_SEEK_END, }; // A semantic node is an operation with optional data @@ -332,6 +338,7 @@ void unit_write(pool_t *pool, i64 unit, u16 target, i64 io_id, void *io_user_dat i64 io_open(i64 name_size, c8 *name, void *user_data); void io_close(i64 f, void *user_data); +i64 io_seek(i64 f, i64 offset, u16 origin, void *user_data); i64 io_read(i64 f, i64 size, void *data, void *user_data); i64 io_write(i64 f, i64 size, void *data, void *user_data); void io_chmod_exe(i64 f, void *user_data); @@ -705,13 +712,170 @@ void unit_set_entry_point(pool_t *pool, i64 unit, i64 entry_point_proc) { // Code generation proc // +#include <stdio.h> // TEMP +#include <stdlib.h> // TEMP + void unit_write(pool_t *pool, i64 unit, u16 target, i64 io_out, void *io_user_data) { assert(pool != NULL && pool->entities != NULL); assert(pool->entities[unit].is_enabled); assert(pool->entities[unit].unit.entry_point_index != UNDEFINED); assert(target == (FORMAT_ELF | ARCH_X86_64)); -// unit_t *u = + // Read dependencies + // + { + unit_t *u = &pool->entities[unit].unit; + + for (i64 i = 0; i < u->link_count; ++i) { + if (u->links[i] == UNDEFINED) + continue; + + i64 index = u->links[i]; + unit_t *l = &pool->entities[index].unit; + + assert(pool->entities[index].is_enabled); + assert(l->type == UNIT_LIBRARY_STATIC); + assert(l->name_size > 0 && l->name_size <= MAX_NAME_SIZE); + + i64 f = io_open(l->name_size, l->name, io_user_data); + + c8 buf0_[MAX_NAME_SIZE + 1] = { 0 }; + memcpy(buf0_, l->name, l->name_size); + printf("\nReading `%s` library...\n\n", buf0_); + + i64 n = 0; + + // Read AR + // + + u8 magic[8]; + + n = io_read(f, sizeof magic, magic, io_user_data); if (n == 0) continue; + + assert(magic[0] == '!'); + assert(magic[1] == '<'); + assert(magic[2] == 'a'); + assert(magic[3] == 'r'); + assert(magic[4] == 'c'); + assert(magic[5] == 'h'); + assert(magic[6] == '>'); + assert(magic[7] == '\n'); + + u32 static offsets[10000] = { 0 }; + i64 file_count = 1; + + for (i64 k = 0;;) { + c8 id[17] = { 0 }; + c8 timestamp[13] = { 0 }; + c8 owner[7] = { 0 }; + c8 group[7] = { 0 }; + c8 mode[9] = { 0 }; + c8 size[11] = { 0 }; + c8 end[2] = { 0 }; + + n = io_read(f, (sizeof id) - 1, id, io_user_data); if (n == 0) break; + n = io_read(f, (sizeof timestamp) - 1, timestamp, io_user_data); if (n == 0) break; + n = io_read(f, (sizeof owner) - 1, owner, io_user_data); if (n == 0) break; + n = io_read(f, (sizeof group) - 1, group, io_user_data); if (n == 0) break; + n = io_read(f, (sizeof mode) - 1, mode, io_user_data); if (n == 0) break; + n = io_read(f, (sizeof size) - 1, size, io_user_data); if (n == 0) break; + n = io_read(f, sizeof end, end, io_user_data); if (n == 0) break; + + assert(end[0] == '\x60'); + assert(end[1] == '\x0a'); + + if (strcmp(id, "/ ") == 0) { + // Symbol table + // + + u32 count_be; + n = io_read(f, 4, &count_be, io_user_data); if (n == 0) break; + + file_count = + (( count_be & 0xffu) << 24) | + (((count_be >> 8) & 0xffu) << 16) | + (((count_be >> 16) & 0xffu) << 8) | + ((count_be >> 24) & 0xffu); + + printf("Symbol table - %lld symbols.\n\n", file_count); + assert(file_count <= (i64) (sizeof offsets / sizeof *offsets)); + + for (u32 j = 0; j < file_count; ++j) { + u32 offset_be; + n = io_read(f, 4, &offset_be, io_user_data); if (n == 0) break; + + offsets[j] = + (( offset_be & 0xffu) << 24) | + (((offset_be >> 8) & 0xffu) << 16) | + (((offset_be >> 16) & 0xffu) << 8) | + ((offset_be >> 24) & 0xffu); + } + if (n == 0) break; + + i64 byte_count = 0; + + for (u32 j = 0; j < file_count; ++j) { + for (;;) { + c8 c; + n = io_read(f, 1, &c, io_user_data); if (n == 0) break; + ++byte_count; + if (c == '\0') + break; + printf("%c", c); + } + if (n == 0) break; + printf(" "); + } + if (n == 0) break; + + printf("\n"); + + if ((byte_count & 1) == 1) { + // align + n = io_seek(f, 1, IO_SEEK_CURSOR, io_user_data); if (n == 0) break; + } + } else if (strcmp(id, "// ") == 0) { + // String table + // + // Skip file + // + + i64 byte_count = atoi(size); + if ((byte_count & 1) == 1) + ++byte_count; // align + + n = io_seek(f, byte_count, IO_SEEK_CURSOR, io_user_data); if (n == 0) break; + } else { + if (strstr(id, "/") != NULL) + *strstr(id, "/") = '\0'; + if (strstr(size, " ") != NULL) + *strstr(size, " ") = '\0'; + printf("%08x: %-16s - %5s bytes\n", offsets[k], id, size); + + // Skip file + // + + i64 byte_count = atoi(size); + if ((byte_count & 1) == 1) + ++byte_count; // align + + n = io_seek(f, byte_count, IO_SEEK_CURSOR, io_user_data); if (n == 0) break; + + if (++k == file_count) + break; + } + } + + io_close(f, io_user_data); + } + } + + #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) + #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data ) + #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data ) + #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data ) + #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data ) + #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data ) u16 ehs = 64; u16 shs = 0; @@ -736,13 +900,6 @@ void unit_write(pool_t *pool, i64 unit, u16 target, i64 io_out, void *io_user_da // ELF header // - #define WRITE(x, n) io_write( io_out, n, x, io_user_data ) - #define WRITE_V(...) io_write( io_out, sizeof((u8[]) {__VA_ARGS__}), (u8[]) {__VA_ARGS__}, io_user_data ) - #define WRITE_DUP(x, n) io_write( io_out, n, (u8[n]) { 0 }, io_user_data ) - #define WRITE_2(x) io_write( io_out, 2, &(u16) { x }, io_user_data ) - #define WRITE_4(x) io_write( io_out, 4, &(u32) { x }, io_user_data ) - #define WRITE_8(x) io_write( io_out, 8, &(u64) { x }, io_user_data ) - WRITE_V( 0x7f, 'E', 'L', 'F' ); // magic WRITE_V( 2 ); // elf64 @@ -805,6 +962,11 @@ void io_close(i64 f, void *user_data) { io_dispatch(IO_CLOSE, &f, NULL, NULL, user_data); } +i64 io_seek(i64 f, i64 offset, u16 origin, void *user_data) { + io_dispatch(IO_SEEK, &f, &offset, &origin, user_data); + return offset; +} + i64 io_read(i64 f, i64 size, void *data, void *user_data) { io_dispatch(IO_READ, &f, &size, data, user_data); return size; @@ -864,6 +1026,19 @@ void io_dispatch(i16 op, i64 *id, i64 *size, void *data, void *user_data) { fclose(*f); break; + case IO_SEEK: { + assert(*f != NULL); + assert(size != NULL); + assert(data != NULL); + + u16 *origin = (u16 *) data; + assert(*origin == IO_SEEK_CURSOR || *origin == IO_SEEK_BEGIN || *origin == IO_SEEK_END); + i32 s = fseek(*f, *size, *origin == IO_SEEK_CURSOR ? SEEK_CUR : + *origin == IO_SEEK_BEGIN ? SEEK_SET : + SEEK_END); + assert(s == 0); + } break; + case IO_READ: assert(*f != NULL); assert(size != NULL); @@ -994,7 +1169,7 @@ int main(int argc, char **argv) { printf("node - %d bytes\n", (i32) sizeof(node_t)); printf("proc - %d bytes\n", (i32) sizeof(proc_t)); printf("unit - %d bytes\n", (i32) sizeof(unit_t)); - printf("entity - %d bytes\n", (i32) sizeof(entity_t)); + printf("entity - %d bytes\n\n", (i32) sizeof(entity_t)); i64 main = p_new("main"); i64 n0 = n_i64(42); |