diff --git a/inc/ft_nm.h b/inc/ft_nm.h index 8592f3a..5489f69 100644 --- a/inc/ft_nm.h +++ b/inc/ft_nm.h @@ -6,15 +6,15 @@ /* By: gtertysh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/05/06 22:37:16 by foton #+# #+# */ -/* Updated: 2019/05/06 22:40:14 by gtertysh ### ########.fr */ +/* Updated: 2019/07/20 15:38:47 by gtertysh ### ########.fr */ /* */ /* ************************************************************************** */ #ifndef FT_NM_H -# define FT_NM_H +#define FT_NM_H -# include -# include +#include +#include typedef struct load_command t_load_command; typedef struct mach_header_64 t_mach_header_64; @@ -23,4 +23,56 @@ typedef struct segment_command_64 t_segment_command_64; typedef struct nlist_64 t_nlist_64; typedef struct section_64 t_section_64; +typedef struct s_nm_file +{ + void *file; + uint32_t size; + int fd; +} t_nm_file; + +typedef struct s_nm_mach_64 +{ + t_mach_header_64 *header; + t_load_command *commands; + t_symtab_command *symbol_table_command; + t_nlist_64 *symbol_table; + char *string_table; +} t_nm_mach_64; + +void init_file +( + t_nm_file *file +); + + +void open_file +( + const char *filename, + t_nm_file *file +); + +void close_file +( + t_nm_file *file +); + + +void macho64 +( + t_nm_file *file +); + +t_symtab_command *find_symbol_table_command +( + t_load_command *lc, + uint32_t count +); + +void print_addr +( + void *addr +); + + + #endif diff --git a/meson.build b/meson.build index c221fb0..314490f 100644 --- a/meson.build +++ b/meson.build @@ -28,7 +28,11 @@ inc = include_directories('inc') install_headers('inc/ft_nm.h') sources = [ - 'src/main.c' + 'src/main.c', + 'src/nm_file.c', + 'src/macho64.c', + 'src/print_address.c', + 'src/find_symbol_table_command.c', ] libft = subproject('libft') diff --git a/src/find_symbol_table_command.c b/src/find_symbol_table_command.c new file mode 100644 index 0000000..690f6a9 --- /dev/null +++ b/src/find_symbol_table_command.c @@ -0,0 +1,26 @@ +#include "ft_nm.h" +#include "stddef.h" + +t_symtab_command *find_symbol_table_command +( + t_load_command *lc, + uint32_t count +) +{ + uint32_t i; + t_symtab_command *sym_tab; + + sym_tab = NULL; + i = 0; + while(i < count) + { + if (lc->cmd == LC_SYMTAB) + { + sym_tab = (t_symtab_command *)lc; + break; + } + lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize); + i++; + } + return sym_tab; +} \ No newline at end of file diff --git a/src/macho64.c b/src/macho64.c new file mode 100644 index 0000000..80ae805 --- /dev/null +++ b/src/macho64.c @@ -0,0 +1,105 @@ +#include "ft_nm.h" +#include "libft.h" +#include + +t_section_64 *find_section +( + t_nm_mach_64 *mach64, + uint32_t index +) +{ + uint32_t i; + uint32_t acc; + t_load_command *lc; + t_section_64 *sections; + t_segment_command_64 *segment; + + lc = mach64->commands; + acc = 0; + i = 0; + while(i < mach64->header->ncmds) + { + if (lc->cmd == LC_SEGMENT_64) + { + segment = (t_segment_command_64 *)lc; + if (segment->nsects + acc >= index) + { + sections = (t_section_64 *)((uintptr_t)segment + + sizeof(t_segment_command_64)); + return (sections + index - acc - 1); + } + acc += segment->nsects; + } + lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize); + i++; + } + return NULL; +} + +void print_symbol_table(t_nm_mach_64 *mach64) +{ + uint32_t j; + t_nlist_64 symbol; + t_section_64 *section; + + j = 0; + while(j < mach64->symbol_table_command->nsyms) + { + symbol = mach64->symbol_table[j]; + int type = symbol.n_type & N_TYPE; + int external = symbol.n_type & N_EXT; + int debug = (symbol.n_type & N_STAB) != 0; + int offset = external ? 0 : 32; + char *name = mach64->string_table + symbol.n_un.n_strx; + + if (debug) + { + j++; + continue; + } + + // some shit herustic should be used + // to determine to print address or not + if (symbol.n_value) + print_addr((void *)symbol.n_value); + else + ft_putstr(" "); + ft_putchar(' '); + if (type == N_UNDF) + ft_putchar('U' + offset); + if (type == N_ABS) + ft_putchar('A' + offset); + if (type == N_SECT) + { + // lookup in which section symbol is located + section = find_section(mach64, symbol.n_sect); + if(ft_strcmp(SECT_TEXT, section->sectname) == 0) + ft_putchar('T' + offset); + else if(ft_strcmp(SECT_DATA, section->sectname) == 0) + ft_putchar('D' + offset); + else if(ft_strcmp(SECT_BSS, section->sectname) == 0) + ft_putchar('B' + offset); + else + ft_putchar('S' + offset); + } + ft_putchar(' '); + ft_putstr(name); + ft_putstr("\n"); + j++; + } +} + +void macho64(t_nm_file *file) +{ + t_nm_mach_64 mach64; + + mach64.header = (t_mach_header_64 *)file->file; + mach64.commands = (t_load_command *)(file->file + sizeof(t_mach_header_64)); + mach64.symbol_table_command = find_symbol_table_command(mach64.commands, + mach64.header->ncmds); + mach64.symbol_table = (t_nlist_64 *) + (mach64.symbol_table_command->symoff + file->file); + mach64.string_table = (char *) + (mach64.symbol_table_command->stroff + file->file); + print_symbol_table(&mach64); +} \ No newline at end of file diff --git a/src/main.c b/src/main.c index a948e27..827c73e 100644 --- a/src/main.c +++ b/src/main.c @@ -3,220 +3,34 @@ /* ::: :::::::: */ /* main.c :+: :+: :+: */ /* +:+ +:+ +:+ */ -/* By: gtertysh +#+ +:+ +#+ */ +/* By: gtertysh +#+ +:+ +#+ */ /* +#+#+#+#+#+ +#+ */ /* Created: 2019/07/13 14:52:27 by gtertysh #+# #+# */ -/* Updated: 2019/07/13 14:52:29 by gtertysh ### ########.fr */ +/* Updated: 2019/07/20 15:21:14 by gtertysh ### ########.fr */ /* */ /* ************************************************************************** */ #include "libft.h" #include "ft_nm.h" -#include -#include -#include -#include -#include -static void print_addr(void *addr) -{ - size_t i; - size_t bit_4; - size_t count; - - count = sizeof(addr) * 2; - i = 0; - while (i < count) - { - bit_4 = ((size_t)addr >> ((count - i - 1) * 4)) & 0xf; - if (bit_4 < 10) - ft_putnbr(bit_4); - else - ft_putchar('a' + bit_4 - 10); - i++; - } -} - -void open_file(const char *filename, int *fd, char **file) -{ - struct stat stat_buff; - - *fd = open(filename, O_RDONLY); - if (*fd == -1) - { - ft_putstr("can't open file\n"); - exit(1); - } - stat(filename, &stat_buff); - if (!S_ISREG(stat_buff.st_mode)) - { - ft_putstr("not a regular file\n"); - close(*fd); - exit(1); - } - *file = NULL; - *file = malloc(stat_buff.st_size); - if (!*file) - { - ft_putstr("can't allocate memory\n"); - close(*fd); - exit(1); - } - read(*fd, *file, stat_buff.st_size); -} - -void close_file(int fd, char *file) -{ - close(fd); - free(file); -} - -t_symtab_command *find_symbol_table_command(t_load_command *lc, uint32_t count) -{ - uint32_t i; - t_symtab_command *sym_tab; - - sym_tab = NULL; - i = 0; - while(i < count) - { - if (lc->cmd == LC_SYMTAB) - { - sym_tab = (t_symtab_command *)lc; - break; - } - lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize); - i++; - } - return sym_tab; -} - -t_section_64 *find_section(t_load_command *lc, uint32_t cmd_num, uint32_t section) -{ - uint32_t i; - uint32_t acc; - t_section_64 *sections; - t_segment_command_64 *segment; - - acc = 0; - i = 0; - while(i < cmd_num) - { - if (lc->cmd == LC_SEGMENT_64) - { - segment = (t_segment_command_64 *)lc; - if (segment->nsects + acc >= section) - { - sections = (t_section_64 *)((uintptr_t)segment + sizeof(t_segment_command_64)); - return (sections + section - acc - 1); - } - acc += segment->nsects; - } - lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize); - i++; - } - return NULL; -} - -void print_symbol_table(t_symtab_command *symtab_cmd, char *file, t_load_command *load_commands, uint32_t cmd_num) -{ - uint32_t j; - t_nlist_64 *symbol_table; - t_nlist_64 symbol; - t_section_64 *section; - char *string_table; - - string_table = file + symtab_cmd->stroff; - symbol_table = (t_nlist_64 *)(file + symtab_cmd->symoff); - j = 0; - while(j < symtab_cmd->nsyms) - { - symbol = symbol_table[j]; - int type = symbol.n_type & N_TYPE; - int external = symbol.n_type & N_EXT; - int debug = (symbol.n_type & N_STAB) != 0; - int offset = external ? 0 : 32; - char *name = string_table + symbol.n_un.n_strx; - - if (debug) - { - j++; - continue; - } - - // some shit herustic should be used - // to determine to print address or not - if (symbol.n_value) - print_addr((void *)symbol.n_value); - else - ft_putstr(" "); - ft_putchar(' '); - if (type == N_UNDF) - ft_putchar('U' + offset); - if (type == N_ABS) - ft_putchar('A' + offset); - if (type == N_SECT) - { - // lookup in which section symbol is located - section = find_section(load_commands, cmd_num, symbol.n_sect); - if(ft_strcmp(SECT_TEXT, section->sectname) == 0) - ft_putchar('T' + offset); - else if(ft_strcmp(SECT_DATA, section->sectname) == 0) - ft_putchar('D' + offset); - else if(ft_strcmp(SECT_BSS, section->sectname) == 0) - ft_putchar('B' + offset); - else - ft_putchar('S' + offset); - ft_putchar(' '); - ft_putnbr(symbol.n_sect); - } - ft_putchar(' '); - ft_putstr(name); - ft_putstr("\n"); - j++; - } -} - -void handle_64(char *file) -{ - t_mach_header_64 *hdr; - t_load_command *load_commands; - t_symtab_command *symtab_cmd; - // t_section_64 *sections; - // t_segment_command_64 *segment_cmd; - - hdr = (t_mach_header_64 *)file; - load_commands = (t_load_command *)(file + sizeof(t_mach_header_64)); - // sections = (t_section_64 *)(file + hdr->sizeofcmds + sizeof(t_mach_header_64)); - symtab_cmd = find_symbol_table_command(load_commands, hdr->ncmds); - print_symbol_table(symtab_cmd, file, load_commands, hdr->ncmds); -} - -void handle_32(char *file) -{ - (void)file; - ft_putstr("TODO\n"); -} void hanldle_file(const char *filename) { - char *file; - int fd; - - open_file(filename, &fd, &file); - uint32_t magic; - - magic = *(uint32_t *)file; + t_nm_file file; + uint32_t magic; + init_file(&file); + open_file(filename, &file); + magic = *(uint32_t *)file.file; if (magic == MH_MAGIC_64) - handle_64(file); - else if (magic == MH_MAGIC) - handle_64(file); - else if (magic == MH_CIGAM || magic == MH_CIGAM_64) - ft_putstr("do not support big endian binaries."); + macho64(&file); + // else if (magic == MH_MAGIC) + // handle_32(file); + // else if (magic == MH_CIGAM || magic == MH_CIGAM_64) + // ft_putstr("do not support big endian binaries."); else ft_putstr("invalid magic number."); - close_file(fd, file); + close_file(&file); } int main(int argc, char **argv) diff --git a/src/nm_file.c b/src/nm_file.c new file mode 100644 index 0000000..a0aaef2 --- /dev/null +++ b/src/nm_file.c @@ -0,0 +1,49 @@ + +#include "ft_nm.h" +#include "libft.h" +#include +#include +#include +#include +#include +#include + +void init_file(t_nm_file *file) +{ + file->fd = -1; + file->file = NULL; + file->size = 0; +} + +void open_file(const char *filename, t_nm_file *file) +{ + struct stat stat_buff; + + file->fd = open(filename, O_RDONLY); + if (file->fd == -1) + { + ft_putstr("can't open file\n"); + exit(1); + } + stat(filename, &stat_buff); + if (!S_ISREG(stat_buff.st_mode)) + { + ft_putstr("not a regular file\n"); + close(file->fd); + exit(1); + } + file->size = stat_buff.st_size; + file->file = mmap(0, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0); + if (file->file == MAP_FAILED) + { + perror("can't mmap file"); + close(file->fd); + exit(1); + } +} + +void close_file(t_nm_file *file) +{ + close(file->fd); + munmap(file->file, file->size); +} \ No newline at end of file diff --git a/src/print_address.c b/src/print_address.c new file mode 100644 index 0000000..2f9763f --- /dev/null +++ b/src/print_address.c @@ -0,0 +1,22 @@ +#include "ft_nm.h" +#include "libft.h" +#include + +void print_addr(void *addr) +{ + size_t i; + size_t bit_4; + size_t count; + + count = sizeof(addr) * 2; + i = 0; + while (i < count) + { + bit_4 = ((size_t)addr >> ((count - i - 1) * 4)) & 0xf; + if (bit_4 < 10) + ft_putnbr(bit_4); + else + ft_putchar('a' + bit_4 - 10); + i++; + } +} \ No newline at end of file