Compare commits
10 commits
5b0cd41383
...
544f01f380
Author | SHA1 | Date | |
---|---|---|---|
544f01f380 | |||
e125f85672 | |||
a748fe4da4 | |||
064cf9ca85 | |||
5ed7fff82c | |||
d991383a26 | |||
d122896244 | |||
7274e13075 | |||
6159ea6e71 | |||
3935cb38a8 |
17 changed files with 608 additions and 66 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -9,3 +9,4 @@
|
|||
/debug_bld
|
||||
/out
|
||||
/ft_nm
|
||||
/ft_otool
|
||||
|
|
70
.vscode/launch.json
vendored
70
.vscode/launch.json
vendored
|
@ -5,7 +5,7 @@
|
|||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "self read",
|
||||
"name": "nm self read",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_bld/ft_nm",
|
||||
|
@ -21,7 +21,7 @@
|
|||
}
|
||||
},
|
||||
{
|
||||
"name": "orig nm read",
|
||||
"name": "nm orig nm read",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_bld/ft_nm",
|
||||
|
@ -35,6 +35,70 @@
|
|||
"osx": {
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nm 32bin",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_bld/ft_nm",
|
||||
"args": ["t/test_binaries/test32"],
|
||||
"preLaunchTask": "build",
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"osx": {
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nm fat",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_bld/ft_nm",
|
||||
"args": ["/usr/bin/javah"],
|
||||
"preLaunchTask": "build",
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"osx": {
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "nm ar",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_bld/ft_nm",
|
||||
"args": ["${workspaceFolder}/debug_bld/subprojects/libft/libft.a"],
|
||||
"preLaunchTask": "build",
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"osx": {
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "otool orig nm read",
|
||||
"type": "cppdbg",
|
||||
"request": "launch",
|
||||
"program": "${workspaceFolder}/debug_bld/ft_otool",
|
||||
"args": ["/usr/bin/nm"],
|
||||
"preLaunchTask": "build",
|
||||
"stopAtEntry": false,
|
||||
"cwd": "${workspaceFolder}",
|
||||
"environment": [],
|
||||
"externalConsole": false,
|
||||
"MIMode": "gdb",
|
||||
"osx": {
|
||||
"MIMode": "lldb"
|
||||
}
|
||||
},
|
||||
]
|
||||
}
|
8
build.sh
8
build.sh
|
@ -5,13 +5,15 @@ OUT_DIR="$PWD/out"
|
|||
RELEASE_BLD_DIR="$PWD/bld"
|
||||
DEBUG_BLD_DIR="$PWD/debug_bld"
|
||||
|
||||
TARGET="ft_nm"
|
||||
FT_NM="ft_nm"
|
||||
FT_OTOOL="ft_otool"
|
||||
|
||||
meson $RELEASE_BLD_DIR --prefix=$OUT_DIR --libdir=$OUT_DIR --includedir=$OUT_DIR --buildtype=release
|
||||
meson $RELEASE_BLD_DIR --prefix=$OUT_DIR --libdir=$OUT_DIR --includedir=$OUT_DIR --bindir=$OUT_DIR --buildtype=release
|
||||
meson $DEBUG_BLD_DIR --buildtype=debug
|
||||
|
||||
ninja -C $DEBUG_BLD_DIR
|
||||
ninja -C $RELEASE_BLD_DIR
|
||||
ninja -C $RELEASE_BLD_DIR install
|
||||
|
||||
ln -sf "$OUT_DIR/bin/$TARGET" "$PWD/$TARGET"
|
||||
ln -sf "$OUT_DIR//$FT_NM" "$PWD/$FT_NM"
|
||||
ln -sf "$OUT_DIR/$FT_OTOOL" "$PWD/$FT_OTOOL"
|
||||
|
|
28
inc/ft_file.h
Normal file
28
inc/ft_file.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef FT_FILE
|
||||
# define FT_FILE
|
||||
|
||||
typedef struct s_file
|
||||
{
|
||||
void *file;
|
||||
uint32_t size;
|
||||
int fd;
|
||||
} t_file;
|
||||
|
||||
void init_file
|
||||
(
|
||||
t_file *file
|
||||
);
|
||||
|
||||
|
||||
void open_file
|
||||
(
|
||||
const char *filename,
|
||||
t_file *file
|
||||
);
|
||||
|
||||
void close_file
|
||||
(
|
||||
t_file *file
|
||||
);
|
||||
|
||||
#endif
|
67
inc/ft_nm.h
67
inc/ft_nm.h
|
@ -6,7 +6,7 @@
|
|||
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2019/05/06 22:37:16 by foton #+# #+# */
|
||||
/* Updated: 2019/07/20 15:38:47 by gtertysh ### ########.fr */
|
||||
/* Updated: 2019/08/17 14:26:16 by gtertysh ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
@ -15,51 +15,63 @@
|
|||
|
||||
#include <mach-o/loader.h>
|
||||
#include <mach-o/nlist.h>
|
||||
#include <mach-o/fat.h>
|
||||
#include <ar.h>
|
||||
#include <stddef.h>
|
||||
#include "ft_file.h"
|
||||
|
||||
typedef struct load_command t_load_command;
|
||||
typedef struct mach_header_64 t_mach_header_64;
|
||||
typedef struct symtab_command t_symtab_command;
|
||||
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 load_command t_load_command;
|
||||
|
||||
typedef struct s_nm_file
|
||||
{
|
||||
void *file;
|
||||
uint32_t size;
|
||||
int fd;
|
||||
} t_nm_file;
|
||||
typedef struct mach_header_64 t_mach_header_64;
|
||||
typedef struct mach_header t_mach_header_32;
|
||||
typedef struct segment_command_64 t_segment_command_64;
|
||||
typedef struct segment_command t_segment_command_32;
|
||||
typedef struct nlist_64 t_nlist_64;
|
||||
typedef struct nlist t_nlist_32;
|
||||
typedef struct section_64 t_section_64;
|
||||
typedef struct section t_section_32;
|
||||
|
||||
typedef struct s_nm_mach_64
|
||||
{
|
||||
t_mach_header_64 *header;
|
||||
t_load_command *commands;
|
||||
t_symtab_command *symbol_table_command;
|
||||
t_segment_command_64 *text_command;
|
||||
t_section_64 *text_section;
|
||||
t_nlist_64 *symbol_table;
|
||||
char *string_table;
|
||||
} t_nm_mach_64;
|
||||
|
||||
void init_file
|
||||
typedef struct s_nm_mach_32
|
||||
{
|
||||
t_mach_header_32 *header;
|
||||
t_load_command *commands;
|
||||
t_symtab_command *symbol_table_command;
|
||||
t_segment_command_32 *text_command;
|
||||
t_section_32 *text_section;
|
||||
t_nlist_32 *symbol_table;
|
||||
char *string_table;
|
||||
} t_nm_mach_32;
|
||||
|
||||
void fat
|
||||
(
|
||||
t_nm_file *file
|
||||
t_file *file
|
||||
);
|
||||
|
||||
|
||||
void open_file
|
||||
void ar
|
||||
(
|
||||
const char *filename,
|
||||
t_nm_file *file
|
||||
t_file *file
|
||||
);
|
||||
|
||||
void close_file
|
||||
(
|
||||
t_nm_file *file
|
||||
);
|
||||
|
||||
|
||||
void macho64
|
||||
(
|
||||
t_nm_file *file
|
||||
t_file *file
|
||||
);
|
||||
|
||||
void macho32
|
||||
(
|
||||
t_file *file
|
||||
);
|
||||
|
||||
t_symtab_command *find_symbol_table_command
|
||||
|
@ -70,9 +82,8 @@ t_symtab_command *find_symbol_table_command
|
|||
|
||||
void print_addr
|
||||
(
|
||||
void *addr
|
||||
size_t addr,
|
||||
size_t count
|
||||
);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
36
meson.build
36
meson.build
|
@ -25,27 +25,41 @@ add_global_arguments(
|
|||
|
||||
inc = include_directories('inc')
|
||||
|
||||
install_headers('inc/ft_nm.h')
|
||||
# install_headers('inc/ft_nm.h')
|
||||
|
||||
sources = [
|
||||
'src/main.c',
|
||||
'src/nm_file.c',
|
||||
'src/macho64.c',
|
||||
'src/print_address.c',
|
||||
'src/find_symbol_table_command.c',
|
||||
nm_sources = [
|
||||
'src/nm/main.c',
|
||||
'src/nm/nm_file.c',
|
||||
'src/nm/macho64.c',
|
||||
'src/nm/macho32.c',
|
||||
'src/nm/fat.c',
|
||||
'src/nm/ar.c',
|
||||
'src/nm/print_address.c',
|
||||
'src/nm/find_symbol_table_command.c',
|
||||
]
|
||||
|
||||
libft = subproject('libft')
|
||||
|
||||
libft_dep = libft.get_variable('libft_dep')
|
||||
otool_sources = [
|
||||
'src/nm/nm_file.c',
|
||||
'src/nm/print_address.c',
|
||||
'src/otool/main.c'
|
||||
]
|
||||
|
||||
libft_dep = subproject('libft').get_variable('libft_dep')
|
||||
|
||||
ft_nm = executable(
|
||||
'ft_nm',
|
||||
sources,
|
||||
nm_sources,
|
||||
include_directories: inc,
|
||||
dependencies: libft_dep,
|
||||
install: true,
|
||||
)
|
||||
|
||||
ft_nm = executable(
|
||||
'ft_otool',
|
||||
otool_sources,
|
||||
include_directories: inc,
|
||||
dependencies: libft_dep,
|
||||
install: true,
|
||||
|
||||
)
|
||||
#subdir('t')
|
||||
|
|
31
src/nm/ar.c
Normal file
31
src/nm/ar.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
#include "ft_nm.h"
|
||||
#include "libft.h"
|
||||
#include <ar.h>
|
||||
|
||||
|
||||
void ar(t_file *file)
|
||||
{
|
||||
struct ar_hdr *runner;
|
||||
char *long_name;
|
||||
size_t offset;
|
||||
t_file obj;
|
||||
|
||||
|
||||
runner = file->file + SARMAG;
|
||||
while ((void *)runner < file->file + file->size)
|
||||
{
|
||||
if (ft_strncmp(runner->ar_name, AR_EFMT1, 3) == 0)
|
||||
{
|
||||
offset = ft_atoi(&runner->ar_name[3]);
|
||||
long_name = (char *)runner + sizeof(struct ar_hdr);
|
||||
ft_putstr("\n");
|
||||
ft_putstr(long_name);
|
||||
ft_putstr("\n");
|
||||
obj.file = (void *)((size_t)runner + sizeof(struct ar_hdr) + offset);
|
||||
obj.size = ft_atoi(runner->ar_size) - offset;
|
||||
if (*(uint32_t *)obj.file == MH_MAGIC_64)
|
||||
macho64(&obj);
|
||||
}
|
||||
runner = (struct ar_hdr *)((size_t)runner + ft_atoi(runner->ar_size) + sizeof(struct ar_hdr));
|
||||
}
|
||||
}
|
33
src/nm/fat.c
Normal file
33
src/nm/fat.c
Normal file
|
@ -0,0 +1,33 @@
|
|||
#include "ft_nm.h"
|
||||
#include "libft.h"
|
||||
#include <stdio.h>
|
||||
|
||||
void fat(t_file *file)
|
||||
{
|
||||
struct fat_arch *arch_runner;
|
||||
struct fat_header *header;
|
||||
t_file arch_file;
|
||||
uint32_t i;
|
||||
|
||||
header = (struct fat_header *)file->file;
|
||||
|
||||
if (header->magic != FAT_CIGAM)
|
||||
{
|
||||
ft_putstr_fd("only 32bit big endian fat binaries supported\n",
|
||||
STDERR_FILENO);
|
||||
exit(1);
|
||||
}
|
||||
arch_runner = file->file + sizeof(struct fat_header);
|
||||
i = 0;
|
||||
while (i < OSSwapInt32(header->nfat_arch))
|
||||
{
|
||||
if (OSSwapInt32(arch_runner->cputype) == CPU_TYPE_X86_64)
|
||||
{
|
||||
arch_file.file = file->file + OSSwapInt32(arch_runner->offset);
|
||||
arch_file.size = OSSwapInt32(arch_runner->size);
|
||||
macho64(&arch_file);
|
||||
}
|
||||
arch_runner = arch_runner + sizeof(struct fat_arch);
|
||||
i++;
|
||||
}
|
||||
}
|
105
src/nm/macho32.c
Normal file
105
src/nm/macho32.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include "ft_nm.h"
|
||||
#include "libft.h"
|
||||
#include <stddef.h>
|
||||
|
||||
static t_section_32 *find_section
|
||||
(
|
||||
t_nm_mach_32 *mach32,
|
||||
uint32_t index
|
||||
)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t acc;
|
||||
t_load_command *lc;
|
||||
t_section_32 *sections;
|
||||
t_segment_command_32 *segment;
|
||||
|
||||
lc = mach32->commands;
|
||||
acc = 0;
|
||||
i = 0;
|
||||
while(i < mach32->header->ncmds)
|
||||
{
|
||||
if (lc->cmd == LC_SEGMENT)
|
||||
{
|
||||
segment = (t_segment_command_32 *)lc;
|
||||
if (segment->nsects + acc >= index)
|
||||
{
|
||||
sections = (t_section_32 *)((uintptr_t)segment +
|
||||
sizeof(t_segment_command_32));
|
||||
return (sections + index - acc - 1);
|
||||
}
|
||||
acc += segment->nsects;
|
||||
}
|
||||
lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize);
|
||||
i++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void print_symbol_table(t_nm_mach_32 *mach32)
|
||||
{
|
||||
uint32_t j;
|
||||
t_nlist_32 symbol;
|
||||
t_section_32 *section;
|
||||
|
||||
j = 0;
|
||||
|
||||
while(j < mach32->symbol_table_command->nsyms)
|
||||
{
|
||||
symbol = mach32->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 = mach32->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(symbol.n_value, 8);
|
||||
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)
|
||||
{
|
||||
section = find_section(mach32, 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 macho32(t_file *file)
|
||||
{
|
||||
t_nm_mach_32 mach32;
|
||||
|
||||
mach32.header = (t_mach_header_32 *)file->file;
|
||||
mach32.commands = (t_load_command *)(file->file + sizeof(t_mach_header_32));
|
||||
mach32.symbol_table_command = find_symbol_table_command(mach32.commands,
|
||||
mach32.header->ncmds);
|
||||
mach32.symbol_table = (t_nlist_32 *)
|
||||
(mach32.symbol_table_command->symoff + file->file);
|
||||
mach32.string_table = (char *)
|
||||
(mach32.symbol_table_command->stroff + file->file);
|
||||
print_symbol_table(&mach32);
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
#include "libft.h"
|
||||
#include <stddef.h>
|
||||
|
||||
t_section_64 *find_section
|
||||
static t_section_64 *find_section
|
||||
(
|
||||
t_nm_mach_64 *mach64,
|
||||
uint32_t index
|
||||
|
@ -36,13 +36,14 @@ t_section_64 *find_section
|
|||
return NULL;
|
||||
}
|
||||
|
||||
void print_symbol_table(t_nm_mach_64 *mach64)
|
||||
static 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];
|
||||
|
@ -61,7 +62,7 @@ void print_symbol_table(t_nm_mach_64 *mach64)
|
|||
// some shit herustic should be used
|
||||
// to determine to print address or not
|
||||
if (symbol.n_value)
|
||||
print_addr((void *)symbol.n_value);
|
||||
print_addr(symbol.n_value, 16);
|
||||
else
|
||||
ft_putstr(" ");
|
||||
ft_putchar(' ');
|
||||
|
@ -71,7 +72,6 @@ void print_symbol_table(t_nm_mach_64 *mach64)
|
|||
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);
|
||||
|
@ -89,7 +89,7 @@ void print_symbol_table(t_nm_mach_64 *mach64)
|
|||
}
|
||||
}
|
||||
|
||||
void macho64(t_nm_file *file)
|
||||
void macho64(t_file *file)
|
||||
{
|
||||
t_nm_mach_64 mach64;
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
/* By: gtertysh <gtertysh@student.unit.ua> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2019/07/13 14:52:27 by gtertysh #+# #+# */
|
||||
/* Updated: 2019/07/20 15:21:14 by gtertysh ### ########.fr */
|
||||
/* Updated: 2019/08/10 16:05:21 by gtertysh ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
@ -16,34 +16,51 @@
|
|||
|
||||
void hanldle_file(const char *filename)
|
||||
{
|
||||
t_nm_file file;
|
||||
t_file file;
|
||||
uint32_t magic;
|
||||
|
||||
// create dispatch table for this bullshit
|
||||
init_file(&file);
|
||||
open_file(filename, &file);
|
||||
magic = *(uint32_t *)file.file;
|
||||
if (magic == MH_MAGIC_64)
|
||||
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 if (magic == MH_MAGIC)
|
||||
macho32(&file);
|
||||
else if (magic == FAT_CIGAM)
|
||||
fat(&file);
|
||||
else if (ft_strncmp(file.file, ARMAG, SARMAG) == 0)
|
||||
ar(&file);
|
||||
else
|
||||
ft_putstr("invalid magic number.");
|
||||
close_file(&file);
|
||||
}
|
||||
|
||||
void print_name(const char *name)
|
||||
{
|
||||
ft_putstr("\n");
|
||||
ft_putstr(name);
|
||||
ft_putstr(":\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc == 1)
|
||||
hanldle_file("a.out");
|
||||
else if (argc == 2)
|
||||
hanldle_file(argv[1]);
|
||||
else
|
||||
{
|
||||
i = 1;
|
||||
while (i < argc)
|
||||
hanldle_file(argv[i++]);
|
||||
{
|
||||
print_name(argv[i]);
|
||||
hanldle_file(argv[i]);
|
||||
i++;
|
||||
}
|
||||
|
||||
}
|
||||
return (0);
|
||||
}
|
|
@ -8,27 +8,27 @@
|
|||
#include <sys/mman.h>
|
||||
#include <stdio.h>
|
||||
|
||||
void init_file(t_nm_file *file)
|
||||
void init_file(t_file *file)
|
||||
{
|
||||
file->fd = -1;
|
||||
file->file = NULL;
|
||||
file->size = 0;
|
||||
}
|
||||
|
||||
void open_file(const char *filename, t_nm_file *file)
|
||||
void open_file(const char *filename, t_file *file)
|
||||
{
|
||||
struct stat stat_buff;
|
||||
|
||||
file->fd = open(filename, O_RDONLY);
|
||||
if (file->fd == -1)
|
||||
{
|
||||
ft_putstr("can't open file\n");
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
stat(filename, &stat_buff);
|
||||
if (!S_ISREG(stat_buff.st_mode))
|
||||
{
|
||||
ft_putstr("not a regular file\n");
|
||||
ft_putstr_fd("not a regular file\n", STDERR_FILENO);
|
||||
close(file->fd);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ void open_file(const char *filename, t_nm_file *file)
|
|||
}
|
||||
}
|
||||
|
||||
void close_file(t_nm_file *file)
|
||||
void close_file(t_file *file)
|
||||
{
|
||||
close(file->fd);
|
||||
munmap(file->file, file->size);
|
|
@ -2,17 +2,15 @@
|
|||
#include "libft.h"
|
||||
#include <stddef.h>
|
||||
|
||||
void print_addr(void *addr)
|
||||
void print_addr(size_t addr, size_t count)
|
||||
{
|
||||
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;
|
||||
bit_4 = (addr >> ((count - i - 1) * 4)) & 0xf;
|
||||
if (bit_4 < 10)
|
||||
ft_putnbr(bit_4);
|
||||
else
|
238
src/otool/main.c
Normal file
238
src/otool/main.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
#include <mach-o/loader.h>
|
||||
#include <mach-o/fat.h>
|
||||
#include <ar.h>
|
||||
#include "ft_file.h"
|
||||
#include "ft_nm.h"
|
||||
#include "libft.h"
|
||||
|
||||
t_segment_command_64 *find_text_command_64
|
||||
(
|
||||
t_load_command *lc,
|
||||
uint32_t count
|
||||
)
|
||||
{
|
||||
uint32_t i;
|
||||
t_segment_command_64 *text_command;
|
||||
|
||||
text_command = NULL;
|
||||
i = 0;
|
||||
while(i < count)
|
||||
{
|
||||
if (lc->cmd == LC_SEGMENT_64 &&
|
||||
ft_strcmp(((t_segment_command_64 *)lc)->segname, SEG_TEXT) == 0)
|
||||
{
|
||||
text_command = (t_segment_command_64 *)lc;
|
||||
break;
|
||||
}
|
||||
lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize);
|
||||
i++;
|
||||
}
|
||||
return text_command;
|
||||
}
|
||||
|
||||
t_segment_command_32 *find_text_command_32
|
||||
(
|
||||
t_load_command *lc,
|
||||
uint32_t count
|
||||
)
|
||||
{
|
||||
uint32_t i;
|
||||
t_segment_command_32 *text_command;
|
||||
|
||||
text_command = NULL;
|
||||
i = 0;
|
||||
while(i < count)
|
||||
{
|
||||
if (lc->cmd == LC_SEGMENT &&
|
||||
ft_strcmp(((t_segment_command_32 *)lc)->segname, SEG_TEXT) == 0)
|
||||
{
|
||||
text_command = (t_segment_command_32 *)lc;
|
||||
break;
|
||||
}
|
||||
lc = (t_load_command *)((uintptr_t)lc + lc->cmdsize);
|
||||
i++;
|
||||
}
|
||||
return text_command;
|
||||
}
|
||||
|
||||
t_section_64 *find_text_section_64
|
||||
(
|
||||
t_segment_command_64 *text_segment
|
||||
)
|
||||
{
|
||||
uint32_t i;
|
||||
t_section_64 *text_section;
|
||||
t_section_64 *runner;
|
||||
|
||||
i = 0;
|
||||
text_section = NULL;
|
||||
runner = (t_section_64 *)((uintptr_t)text_segment +
|
||||
sizeof(t_segment_command_64));
|
||||
|
||||
while(i < text_segment->nsects)
|
||||
{
|
||||
if (ft_strcmp(runner->sectname, SECT_TEXT) == 0)
|
||||
{
|
||||
text_section = runner;
|
||||
break;
|
||||
}
|
||||
runner = (t_section_64 *)((uintptr_t)runner + sizeof(t_section_64));
|
||||
i++;
|
||||
}
|
||||
return (text_section);
|
||||
}
|
||||
|
||||
t_section_32 *find_text_section_32
|
||||
(
|
||||
t_segment_command_32 *text_segment
|
||||
)
|
||||
{
|
||||
uint32_t i;
|
||||
t_section_32 *text_section;
|
||||
t_section_32 *runner;
|
||||
|
||||
i = 0;
|
||||
text_section = NULL;
|
||||
runner = (t_section_32 *)((uintptr_t)text_segment +
|
||||
sizeof(t_segment_command_32));
|
||||
|
||||
while(i < text_segment->nsects)
|
||||
{
|
||||
if (ft_strcmp(runner->sectname, SECT_TEXT) == 0)
|
||||
{
|
||||
text_section = runner;
|
||||
break;
|
||||
}
|
||||
runner = (t_section_32 *)((uintptr_t)runner + sizeof(t_section_32));
|
||||
i++;
|
||||
}
|
||||
return (text_section);
|
||||
}
|
||||
|
||||
void print_text_64
|
||||
(
|
||||
t_nm_mach_64 *mach64,
|
||||
t_file *file
|
||||
)
|
||||
{
|
||||
size_t text;
|
||||
size_t addr;
|
||||
uint64_t i;
|
||||
uint64_t j;
|
||||
|
||||
text = (size_t)file->file + mach64->text_section->offset;
|
||||
addr = mach64->text_section->addr;
|
||||
i = 0;
|
||||
while(i < mach64->text_section->size)
|
||||
{
|
||||
print_addr(addr + i, 16);
|
||||
ft_putstr("\t");
|
||||
j = 0;
|
||||
while(i < mach64->text_section->size && j < 16)
|
||||
{
|
||||
print_addr(*(char *)(text + i), 2);
|
||||
ft_putstr(" ");
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
ft_putstr("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void print_text_32
|
||||
(
|
||||
t_nm_mach_32 *mach32,
|
||||
t_file *file
|
||||
)
|
||||
{
|
||||
size_t text;
|
||||
size_t addr;
|
||||
uint64_t i;
|
||||
uint64_t j;
|
||||
|
||||
text = (size_t)file->file + mach32->text_section->offset;
|
||||
addr = mach32->text_section->addr;
|
||||
i = 0;
|
||||
while(i < mach32->text_section->size)
|
||||
{
|
||||
print_addr(addr + i, 8);
|
||||
ft_putstr("\t");
|
||||
j = 0;
|
||||
while(i < mach32->text_section->size && j < 8)
|
||||
{
|
||||
print_addr(*(char *)(text + i), 2);
|
||||
ft_putstr(" ");
|
||||
j++;
|
||||
i++;
|
||||
}
|
||||
ft_putstr("\n");
|
||||
}
|
||||
}
|
||||
|
||||
void otool64(t_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.text_command = find_text_command_64(mach64.commands,
|
||||
mach64.header->ncmds);
|
||||
mach64.text_section = find_text_section_64(mach64.text_command);
|
||||
print_text_64(&mach64, file);
|
||||
}
|
||||
|
||||
void otool32(t_file *file)
|
||||
{
|
||||
t_nm_mach_32 mach32;
|
||||
|
||||
mach32.header = (t_mach_header_32 *)file->file;
|
||||
mach32.commands = (t_load_command *)(file->file + sizeof(t_mach_header_32));
|
||||
mach32.text_command = find_text_command_32(mach32.commands,
|
||||
mach32.header->ncmds);
|
||||
mach32.text_section = find_text_section_32(mach32.text_command);
|
||||
print_text_32(&mach32, file);
|
||||
}
|
||||
|
||||
void hanldle_file(const char *filename)
|
||||
{
|
||||
t_file file;
|
||||
uint32_t magic;
|
||||
|
||||
// create dispatch table for this bullshit
|
||||
init_file(&file);
|
||||
open_file(filename, &file);
|
||||
magic = *(uint32_t *)file.file;
|
||||
if (magic == MH_MAGIC_64)
|
||||
otool64(&file);
|
||||
else if (magic == MH_MAGIC)
|
||||
otool32(&file);
|
||||
// else if (magic == FAT_CIGAM)
|
||||
// fat(&file);
|
||||
// else if (ft_strncmp(file.file, ARMAG, SARMAG) == 0)
|
||||
// ar(&file);
|
||||
else
|
||||
ft_putstr("invalid magic number.");
|
||||
close_file(&file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (argc == 1)
|
||||
{
|
||||
ft_putstr_fd("at least one file must be specified\n", STDERR_FILENO);
|
||||
return (1);
|
||||
}
|
||||
|
||||
i = 1;
|
||||
while(i < argc)
|
||||
{
|
||||
ft_putstr(argv[i]);
|
||||
ft_putstr(":\n");
|
||||
ft_putstr("Contents of (__TEXT,__text) section\n");
|
||||
hanldle_file(argv[i]);
|
||||
i++;
|
||||
}
|
||||
return (0);
|
||||
}
|
BIN
t/test_binaries/fat_dynamic.dylib
Executable file
BIN
t/test_binaries/fat_dynamic.dylib
Executable file
Binary file not shown.
BIN
t/test_binaries/test32
Executable file
BIN
t/test_binaries/test32
Executable file
Binary file not shown.
Loading…
Reference in a new issue