From 0451a89dce186c65c20788b0bd6863b634a4f7de Mon Sep 17 00:00:00 2001 From: gbrochar Date: Mon, 14 Oct 2024 21:56:32 +0200 Subject: [PATCH] feat: basic flags --- inc/ft_nm.h | 12 ++++- libft | 2 +- src/ft_printf.c | 8 ++++ src/main.c | 11 ++--- src/nm.c | 113 +++++++++++++++++++++++++++++++++++++++++------- src/old_main.c | 62 ++++++++++++++++++++++++++ 6 files changed, 184 insertions(+), 24 deletions(-) create mode 100644 src/old_main.c diff --git a/inc/ft_nm.h b/inc/ft_nm.h index 15f0665..8ec11db 100644 --- a/inc/ft_nm.h +++ b/inc/ft_nm.h @@ -16,8 +16,8 @@ # define FT_NM_FAILURE -1 typedef enum e_verbosity { - DEFAULT_VERBOSITY, ALL, + DEFAULT_VERBOSITY, GLOBAL, UNDEFINED } t_verbosity; @@ -28,6 +28,12 @@ typedef enum e_ordering { NOSORT } t_ordering; +typedef struct s_entry { + t_verbosity verbosity; + char *string; + char *symbol; +} t_entry; + typedef struct s_env { char *bin_name; t_verbosity verbosity; @@ -50,8 +56,10 @@ void *fetch(t_mapped_file mapped_file, size_t offset, size_t fetch_size); int nm32(t_mapped_file mapped_file); -int nm64(t_mapped_file mapped_file); +int nm64(t_mapped_file mapped_file, char *path, t_verbosity verbosity, t_ordering ordering); int get_header64(t_mapped_file mapped_file, Elf64_Ehdr *header); +char ft_get_hex_digit(char c); + #endif diff --git a/libft b/libft index a9a3c47..1cab237 160000 --- a/libft +++ b/libft @@ -1 +1 @@ -Subproject commit a9a3c473d5898d1eacfe2c036266fe0f810b0b53 +Subproject commit 1cab2379213f62f814312dc2cc7b0f3aa65268fc diff --git a/src/ft_printf.c b/src/ft_printf.c index 047d631..ac2141b 100644 --- a/src/ft_printf.c +++ b/src/ft_printf.c @@ -1,5 +1,13 @@ #include "ft_nm.h" +char ft_get_hex_digit(char c) { + if (c > 9) { + return c + 'W'; + } else { + return c + '0'; + } +} + void ft_print_hex_digit(char c) { if (c > 9) { ft_putchar(c + 'W'); diff --git a/src/main.c b/src/main.c index 2b4995a..e7089fe 100644 --- a/src/main.c +++ b/src/main.c @@ -28,7 +28,7 @@ int parse_options(char *options, t_env *env, bool *use_options) { return -2; break; case 'a': - if (env->verbosity < ALL) + if (env->verbosity < ALL || env->verbosity == DEFAULT_VERBOSITY) env->verbosity = ALL; break; case 'g': @@ -58,6 +58,7 @@ int parse_arguments(int ac, char **av, t_env *env) { bool use_options = true; if (ac > 0) { env->bin_name = ft_strdup(av[0]); + env->bin_name = ft_strdup("nm"); } for (int i = 1; i < ac; i++) { if (ft_strlen(av[i]) > 0 && av[i][0] == '-' && use_options) { @@ -76,7 +77,7 @@ int parse_arguments(int ac, char **av, t_env *env) { return 0; } -int nm(char *path) { +int nm(char *path, t_verbosity verbosity, t_ordering ordering) { int fd = open(path, O_RDONLY); if (fd == -1) { ft_nm_error(path); @@ -111,7 +112,7 @@ int nm(char *path) { } } else if (ident[EI_CLASS] == ELFCLASS64) { - if (nm64(mapped_file) == FT_NM_FAILURE) { + if (nm64(mapped_file, path, verbosity, ordering) == FT_NM_FAILURE) { ft_printf("sss", "nm: ", path, ": file format not recognized\n"); return 0; } @@ -135,12 +136,12 @@ int main(int ac, char **av) { return error; } if (env.list_len == 1) { - nm(env.list->content); + nm(env.list->content, env.verbosity, env.ordering); return 0; } while (env.list) { ft_printf("\ns:\n", env.list->content); - nm(env.list->content); + nm(env.list->content, env.verbosity, env.ordering); env.list = env.list->next; } return 0; diff --git a/src/nm.c b/src/nm.c index 083347f..b33fcce 100644 --- a/src/nm.c +++ b/src/nm.c @@ -5,7 +5,6 @@ void print_section(Elf64_Shdr sec); void print_symbol(Elf64_Sym sym); char *get_sym_char(Elf64_Sym sym, Elf64_Shdr sec) { - //ppp(sym, sec); // if ((sec.sh_flags & SHF_COMPRESSED) == SHF_COMPRESSED) { // return ("N"); // } @@ -104,7 +103,7 @@ char *get_sym_char(Elf64_Sym sym, Elf64_Shdr sec) { } } if (sym.st_shndx == SHN_UNDEF) { -//return ("U"); + //return ("U"); if (ELF64_ST_BIND(sym.st_info) == STB_LOCAL) { return ("u"); } @@ -140,34 +139,59 @@ char *get_sym_char(Elf64_Sym sym, Elf64_Shdr sec) { return ("n"); } -int nm64(t_mapped_file mapped_file) { +int strcmp_nm(t_list *a, t_list *b) { + (void)a; + (void)b; + return 1; +} + +int reverse(t_list *a, t_list *b) { + return strcmp_nm(b, a); +} + +int nosort(t_list *a, t_list *b) { + (void)a; + (void)b; + return -1; +} + +int nm64(t_mapped_file mapped_file, char *path, t_verbosity verbosity, t_ordering ordering) { + t_list *list = NULL; + t_entry *entry = (t_entry *)malloc(sizeof(t_entry)); + if (!entry) + return FT_NM_FAILURE; Elf64_Ehdr header; if (get_header64(mapped_file, &header) == FT_NM_FAILURE) { return FT_NM_FAILURE; } uint64_t addr = header.e_shoff + header.e_shentsize * header.e_shstrndx; Elf64_Shdr shstrtb; - ft_memcpy(&shstrtb, mapped_file.ptr + addr, header.e_shentsize); + shstrtb = *(Elf64_Shdr *)fetch(mapped_file, addr, header.e_shentsize); for (int i = 0; i < header.e_shnum; i++) { uint64_t addr = header.e_shoff + header.e_shentsize * i; Elf64_Shdr sh; - ft_memcpy(&sh, mapped_file.ptr + addr, header.e_shentsize); + sh = *(Elf64_Shdr *)fetch(mapped_file, addr, header.e_shentsize); if (sh.sh_type == SHT_SYMTAB) { uint64_t addr2 = header.e_shoff + header.e_shentsize * sh.sh_link; Elf64_Shdr strtab; - ft_memcpy(&strtab, mapped_file.ptr + addr2, header.e_shentsize); + strtab = *(Elf64_Shdr *)fetch(mapped_file, addr2, header.e_shentsize); + char first = *(char *)fetch(mapped_file, strtab.sh_offset, 1); + char last = *(char *)fetch(mapped_file, strtab.sh_offset + strtab.sh_size - 1, 1); + if (first != '\0' || last != '\0') { + return FT_NM_FAILURE; + } for (uint64_t j = sh.sh_entsize; j < sh.sh_size; j += sh.sh_entsize) { Elf64_Sym sym; Elf64_Shdr sec; - ft_memcpy(&sym, mapped_file.ptr + sh.sh_offset + j, sh.sh_entsize); + sym = *(Elf64_Sym *)fetch(mapped_file, sh.sh_offset + j, sh.sh_entsize); if (sym.st_shndx < header.e_shnum) { - ft_memcpy(&sec, mapped_file.ptr + header.e_shoff + header.e_shentsize * sym.st_shndx, header.e_shentsize); + sec = *(Elf64_Shdr *)fetch(mapped_file, header.e_shoff + header.e_shentsize * sym.st_shndx, header.e_shentsize); } char *str; char *sec_str; Elf64_Shdr shdr; if (sym.st_shndx != SHN_ABS) { - ft_memcpy(&shdr, mapped_file.ptr + header.e_shoff + header.e_shentsize * sym.st_shndx, header.e_shentsize); + shdr = *(Elf64_Shdr *)fetch(mapped_file, header.e_shoff + header.e_shentsize * sym.st_shndx, header.e_shentsize); sec_str = ft_strdup(mapped_file.ptr + shstrtb.sh_offset + shdr.sh_name); } else { sec_str = ft_strdup(""); @@ -178,26 +202,83 @@ int nm64(t_mapped_file mapped_file) { else { str = sec_str; } + // ici la str (le symbole) est bon, on la charge dans le truc, ensuite on genere la vrai string a afficher, avant de sort + entry->symbol = ft_strdup(str); + free(str); char *sym_char = ft_strdup(get_sym_char(sym, sec)); if (ft_strnstr(sec_str, ".debug", 6) && ft_strequ(sym_char, "n")) { free(sym_char); sym_char = ft_strdup("N"); } - if (sym.st_value) { - ft_printf("X s ss", sym.st_value, sym_char, str, "\n"); - } else { - if (ft_strcmp(sym_char, "U") && ft_strcmp(sym_char, "w") && ft_strcmp(sym_char, "v")) { - ft_printf("X s ss", sym.st_value, sym_char, str, "\n"); + // ici le sym char a ete calculer, a partir de la on determine la verbosity + // ici on fait if entry->verbosity >= verbosity, si c'est pas bon on skip toute la suite + entry->verbosity = DEFAULT_VERBOSITY; + if (sym_char[0] == 'a') + entry->verbosity = ALL; + if (sym_char[0] == 'u' || sym_char[0] == 'v' || sym_char[0] == 'w' || (sym_char[0] >= 'A' && sym_char[0] <= 'Z')) + entry->verbosity = GLOBAL; + if (sym_char[0] == 'w' || sym_char[0] == 'U') + entry->verbosity = UNDEFINED; + if (entry->verbosity >= verbosity) { + // ici on genere la string a afficher + // pad ' ' symchar ' ' symbol name \n \0 + size_t entry_string_len = 16 + 1 + 1 + 1 + ft_strlen(entry->symbol) + 1 + 1; + entry->string = (char *)malloc(sizeof(char) * entry_string_len); + if (!entry->string) + return FT_NM_FAILURE; + entry->string[entry_string_len - 1] = '\0'; + entry->string[entry_string_len - 2] = '\n'; + entry->string[16] = ' '; + entry->string[17] = sym_char[0]; + entry->string[18] = ' '; + ft_memcpy(entry->string + 19, entry->symbol, ft_strlen(entry->symbol)); + if (sym.st_value) { + for (char i = 15; i >= 0; i--) { + entry->string[15 - i] = ft_get_hex_digit((sym.st_value >> i * 4) & 0xF); + } } else { - ft_printf("P s ss", sym_char, str, "\n"); + if (ft_strcmp(sym_char, "U") && ft_strcmp(sym_char, "w") && ft_strcmp(sym_char, "v")) { + + for (char i = 15; i >= 0; i--) { + entry->string[15 - i] = ft_get_hex_digit((sym.st_value >> i * 4) & 0xF); + } + } else { + for (int i = 0; i < 16; i++) + entry->string[i] = ' '; + } } + free(sym_char); + // ensuite un switch ordering avec un ft_lstinsert (pointeur sur fonction serait plus opti mais osef) + switch (ordering) { + case NOSORT: + ft_lstinsert(&list, ft_lstnew((void *)entry, sizeof(t_entry)), &nosort); + break; + case REVERSE: + ft_lstinsert(&list, ft_lstnew((void *)entry, sizeof(t_entry)), &reverse); + break; + case DEFAULT_ORDERING: + ft_lstinsert(&list, ft_lstnew((void *)entry, sizeof(t_entry)), &strcmp_nm); + break; + } + // pas de bst oops :D + fflush(stdout); } - fflush(stdout); } } char *str = ft_strdup(mapped_file.ptr + shstrtb.sh_offset + sh.sh_name); free(str); } + // ici on affiche tout ou no symbols en cas de list vide + if (list) { + while (list) { + t_entry *my_entry = (t_entry *)list->content; + ft_putstr(my_entry->string); + list = list->next; + } + } + else { + ft_printf("sss", "nm: ", path, ": no symbols\n"); + } return FT_NM_SUCCESS; } diff --git a/src/old_main.c b/src/old_main.c new file mode 100644 index 0000000..071cecb --- /dev/null +++ b/src/old_main.c @@ -0,0 +1,62 @@ +#include "ft_nm.h" + +int main(int ac, char **av) { + char *path = ft_strdup("a.out"); + + if (ac > 1) { + free(path); + path = ft_strdup(av[1]); + } + + int fd = open(path, O_RDONLY); + if (fd == -1) { + ft_nm_error(path); + free(path); + exit (EXIT_FAILURE); + } + + struct stat stat; + if (fstat(fd, &stat) == -1) { + ft_nm_error(path); + free(path); + exit (EXIT_FAILURE); + } + + t_mapped_file mapped_file; + +// ft_printf("sds", "file size: ", stat.st_size, "\n"); + mapped_file.ptr = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + mapped_file.size = stat.st_size; + if (mapped_file.ptr != MAP_FAILED) { + void *ident_ptr = fetch(mapped_file, 0, EI_NIDENT); + unsigned char ident[EI_NIDENT]; + if (!ident_ptr) { + ft_printf("sss", "nm: ", path, ": file format not recognized\n"); + free(path); + exit(EXIT_FAILURE); + } + ft_memcpy(ident, ident_ptr, EI_NIDENT); + if (check_ident(ident) == FT_NM_FAILURE) { + ft_printf("sss", "nm: ", path, ": file format not recognized\n"); + free(path); + exit(EXIT_FAILURE); + } + if (ident[EI_CLASS] == ELFCLASS32) { + if (nm32(mapped_file) == FT_NM_FAILURE) { + ft_printf("sss", "nm: ", path, ": file format not recognized\n"); + free(path); + exit(EXIT_FAILURE); + } + } + else if (ident[EI_CLASS] == ELFCLASS64) { + if (nm64(mapped_file) == FT_NM_FAILURE) { + ft_printf("sss", "nm: ", path, ": file format not recognized\n"); + free(path); + exit(EXIT_FAILURE); + } + } + } + free(path); + return 0; +} +