libelfin wrapper WIP!
This commit is contained in:
12
Makefile
12
Makefile
@@ -1,6 +1,7 @@
|
|||||||
CC=gcc
|
CC=gcc
|
||||||
CFLAGS=-MD -MP -ggdb -I./mujs
|
CXX=g++
|
||||||
LDFLAGS=-lm -lelf
|
CFLAGS=-MD -MP -gdwarf -I./mujs
|
||||||
|
LDFLAGS=-lm -ldwarf++ -lelf++ -lstdc++
|
||||||
SRCS=debugus.c linenoise.c hash.c pmparser.c
|
SRCS=debugus.c linenoise.c hash.c pmparser.c
|
||||||
OBJS=$(patsubst %.c,%.o,$(SRCS))
|
OBJS=$(patsubst %.c,%.o,$(SRCS))
|
||||||
DEPS=$(patsubst %.c,%.d,$(SRCS))
|
DEPS=$(patsubst %.c,%.d,$(SRCS))
|
||||||
@@ -10,7 +11,7 @@ all: debugus .debugusrc1.js test
|
|||||||
test: test.o
|
test: test.o
|
||||||
$(CC) -gdwarf -o $@ $^
|
$(CC) -gdwarf -o $@ $^
|
||||||
|
|
||||||
debugus: $(OBJS) ./mujs/build/debug/libmujs.o
|
debugus: $(OBJS) ./mujs/build/debug/libmujs.o ./libelfin_wrap.o
|
||||||
$(CC) -o $@ $^ $(LDFLAGS)
|
$(CC) -o $@ $^ $(LDFLAGS)
|
||||||
|
|
||||||
.debugusrc1.js: test .debugusrc1.js.txt
|
.debugusrc1.js: test .debugusrc1.js.txt
|
||||||
@@ -19,9 +20,12 @@ debugus: $(OBJS) ./mujs/build/debug/libmujs.o
|
|||||||
./mujs/build/debug/libmujs.o:
|
./mujs/build/debug/libmujs.o:
|
||||||
make -C mujs -j$(shell nproc)
|
make -C mujs -j$(shell nproc)
|
||||||
|
|
||||||
|
./libelfin_wrap.o: ./libelfin_wrap.cpp
|
||||||
|
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
-include $(DEPS)
|
-include $(DEPS)
|
||||||
|
|
||||||
clean: $(OBJS) test.o $(DEPS)
|
clean: $(OBJS) test.o $(DEPS) .debugusrc1.js
|
||||||
rm -f $^
|
rm -f $^
|
||||||
make -C mujs clean
|
make -C mujs clean
|
||||||
|
|
||||||
|
|||||||
87
debugus.c
87
debugus.c
@@ -8,8 +8,6 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <libelf.h>
|
|
||||||
#include <gelf.h>
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
@@ -22,6 +20,7 @@
|
|||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
#include "pmparser.h"
|
#include "pmparser.h"
|
||||||
#include "da.h"
|
#include "da.h"
|
||||||
|
#include "libelfin_wrap.h"
|
||||||
|
|
||||||
#define LOG_ERR(fmt, ...) fprintf(stderr, "Error: " fmt, ##__VA_ARGS__)
|
#define LOG_ERR(fmt, ...) fprintf(stderr, "Error: " fmt, ##__VA_ARGS__)
|
||||||
#define LOG_INF(fmt, ...) fprintf(stdout, "Info: " fmt, ##__VA_ARGS__)
|
#define LOG_INF(fmt, ...) fprintf(stdout, "Info: " fmt, ##__VA_ARGS__)
|
||||||
@@ -146,23 +145,12 @@ void brk_disable(Brk *brk)
|
|||||||
brk->enabled = false;
|
brk->enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const char *name;
|
|
||||||
uintptr_t addr;
|
|
||||||
} Symbol;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
Symbol *items;
|
|
||||||
size_t count, capacity;
|
|
||||||
} Symbols;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char *file;
|
const char *file;
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
js_State *js;
|
js_State *js;
|
||||||
HashTable brks;
|
HashTable brks;
|
||||||
uintptr_t program_load_offset;
|
uintptr_t program_load_offset;
|
||||||
Symbols symbols;
|
|
||||||
HashTable js_descs;
|
HashTable js_descs;
|
||||||
} Dbg;
|
} Dbg;
|
||||||
|
|
||||||
@@ -184,11 +172,20 @@ void dbg_handle_sigtrap(Dbg *dbg, siginfo_t info)
|
|||||||
void dbg_set_rip(Dbg *dbg, uint64_t v);
|
void dbg_set_rip(Dbg *dbg, uint64_t v);
|
||||||
uint64_t dbg_get_rip(Dbg *dbg);
|
uint64_t dbg_get_rip(Dbg *dbg);
|
||||||
|
|
||||||
|
AddrInfo *ai;
|
||||||
|
|
||||||
switch (info.si_code) {
|
switch (info.si_code) {
|
||||||
case SI_KERNEL:
|
case SI_KERNEL:
|
||||||
case TRAP_BRKPT:
|
case TRAP_BRKPT:
|
||||||
dbg_set_rip(dbg, dbg_get_rip(dbg) - 1);
|
dbg_set_rip(dbg, dbg_get_rip(dbg) - 1);
|
||||||
LOG_INF("Hit breakpoint at 0x%"PRIxPTR"\n", dbg_get_rip(dbg));
|
ai = libelfin_wrap_info_from_rip(dbg_get_rip(dbg));
|
||||||
|
if (ai != NULL) {
|
||||||
|
LOG_INF("Hit breakpoint at 0x%"PRIxPTR", %s:%zu\n", dbg_get_rip(dbg),
|
||||||
|
ai->file, (size_t)ai->line);
|
||||||
|
libelfin_wrap_free_info(ai);
|
||||||
|
} else {
|
||||||
|
LOG_INF("Hit breakpoint at 0x%"PRIxPTR"\n", dbg_get_rip(dbg));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
case TRAP_TRACE:
|
case TRAP_TRACE:
|
||||||
return;
|
return;
|
||||||
@@ -450,16 +447,6 @@ void dbg_js_mwr(js_State *js)
|
|||||||
js_pushundefined(js);
|
js_pushundefined(js);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbg_js_lsm(js_State *js)
|
|
||||||
{
|
|
||||||
Dbg *dbg = getdbg();
|
|
||||||
for (int i = 0; i < dbg->symbols.count; i++) {
|
|
||||||
Symbol *sym = &dbg->symbols.items[i];
|
|
||||||
LOG_INF("Symbol %s at %"PRIxPTR"\n", sym->name, sym->addr);
|
|
||||||
}
|
|
||||||
js_pushundefined(js);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dbg_js_help(js_State *js)
|
void dbg_js_help(js_State *js)
|
||||||
{
|
{
|
||||||
Dbg *dbg = getdbg();
|
Dbg *dbg = getdbg();
|
||||||
@@ -499,7 +486,6 @@ void dbg_init_js(Dbg *dbg)
|
|||||||
make_js_func(sr, 2, "Set register value, ARGS=Register name:string,Register value:hex string");
|
make_js_func(sr, 2, "Set register value, ARGS=Register name:string,Register value:hex string");
|
||||||
make_js_func(mrd, 1, "Read memory at address, ARGS=Address:hex string");
|
make_js_func(mrd, 1, "Read memory at address, ARGS=Address:hex string");
|
||||||
make_js_func(mwr, 2, "Write memory at address, ARGS=Address:hex string,Value:hex string");
|
make_js_func(mwr, 2, "Write memory at address, ARGS=Address:hex string,Value:hex string");
|
||||||
make_js_func(lsm, 0, "List all symbols, ARGS=None");
|
|
||||||
make_js_func(help, 0, "Print help information, ARGS=None");
|
make_js_func(help, 0, "Print help information, ARGS=None");
|
||||||
|
|
||||||
#undef make_js_func
|
#undef make_js_func
|
||||||
@@ -544,58 +530,16 @@ void dbg_load_script(Dbg *dbg, const char *script_path)
|
|||||||
fclose(script);
|
fclose(script);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbg_load_symbols(Dbg *dbg)
|
void dbg_libelfin_wrap_init(Dbg *dbg)
|
||||||
{
|
{
|
||||||
FILE *bin = fopen(dbg->file, "rb");
|
FILE *bin = fopen(dbg->file, "rb");
|
||||||
if (bin == NULL) {
|
if (bin == NULL) {
|
||||||
LOG_ERR("Cannot load symbols from file\n");
|
LOG_ERR("could not open file %s: %s\n", dbg->file, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Elf *elf;
|
libelfin_wrap_init(fileno(bin));
|
||||||
Elf_Scn *scn = NULL;
|
|
||||||
GElf_Shdr shdr;
|
|
||||||
Elf_Data *data;
|
|
||||||
GElf_Sym sym;
|
|
||||||
|
|
||||||
elf_version(EV_CURRENT);
|
|
||||||
|
|
||||||
elf = elf_begin(fileno(bin), ELF_C_READ, NULL);
|
|
||||||
if (elf == NULL) {
|
|
||||||
LOG_ERR("Could not parse elf\n");
|
|
||||||
fclose(bin);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ((scn = elf_nextscn(elf, scn)) != NULL) {
|
|
||||||
gelf_getshdr(scn, &shdr);
|
|
||||||
if (shdr.sh_type == SHT_SYMTAB) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
data = elf_getdata(scn, NULL);
|
|
||||||
int count = shdr.sh_size / shdr.sh_entsize;
|
|
||||||
|
|
||||||
for (int i = 0; i < count; i++) {
|
|
||||||
gelf_getsym(data, i, &sym);
|
|
||||||
if (sym.st_info != 2 /*func*/) {
|
|
||||||
char *name = elf_strptr(elf, shdr.sh_link, sym.st_name);
|
|
||||||
size_t len = strlen(name);
|
|
||||||
if (len == 0 || sym.st_value == 0x0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *n = malloc(len+1);
|
|
||||||
strcpy(n, name);
|
|
||||||
n[len] = '\0';
|
|
||||||
|
|
||||||
Symbol symbol = { .name = name, .addr = dbg->program_load_offset + (uintptr_t)sym.st_value };
|
|
||||||
da_append(&dbg->symbols, symbol);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
elf_end(elf);
|
|
||||||
fclose(bin);
|
fclose(bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -607,8 +551,8 @@ void dbg_init(Dbg *dbg, const char *file, pid_t pid)
|
|||||||
hashtable_init(&dbg->js_descs, MAX_JS_FUNCS);
|
hashtable_init(&dbg->js_descs, MAX_JS_FUNCS);
|
||||||
dbg_init_js(dbg);
|
dbg_init_js(dbg);
|
||||||
dbg_init_load_offset(dbg);
|
dbg_init_load_offset(dbg);
|
||||||
|
dbg_libelfin_wrap_init(dbg);
|
||||||
hashtable_init(&dbg->brks, MAX_BRKS);
|
hashtable_init(&dbg->brks, MAX_BRKS);
|
||||||
dbg_load_symbols(dbg);
|
|
||||||
dbg_load_script(dbg, INIT_SCRIPT);
|
dbg_load_script(dbg, INIT_SCRIPT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,7 +561,6 @@ void dbg_deinit(Dbg *dbg)
|
|||||||
js_freestate(dbg->js);
|
js_freestate(dbg->js);
|
||||||
hashtable_deinit(&dbg->brks);
|
hashtable_deinit(&dbg->brks);
|
||||||
hashtable_deinit(&dbg->js_descs);
|
hashtable_deinit(&dbg->js_descs);
|
||||||
da_deinit(&dbg->symbols);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dbg_loop(Dbg *dbg)
|
void dbg_loop(Dbg *dbg)
|
||||||
|
|||||||
43
libelfin_wrap.cpp
Normal file
43
libelfin_wrap.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#include <libelfin/dwarf/dwarf++.hh>
|
||||||
|
#include <libelfin/elf/elf++.hh>
|
||||||
|
|
||||||
|
#include "libelfin_wrap.h"
|
||||||
|
|
||||||
|
static elf::elf gelf;
|
||||||
|
static dwarf::dwarf gdwarf;
|
||||||
|
|
||||||
|
DEBUGUS_EXTERNC void libelfin_wrap_init(int fd)
|
||||||
|
{
|
||||||
|
gelf = elf::elf{elf::create_mmap_loader(fd)};
|
||||||
|
gdwarf = dwarf::dwarf{dwarf::elf::create_loader(gelf)};
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGUS_EXTERNC AddrInfo *libelfin_wrap_info_from_rip(uint64_t rip)
|
||||||
|
{
|
||||||
|
for (auto &cu : gdwarf.compilation_units()) {
|
||||||
|
if (die_pc_range(cu.root()).contains(rip)) {
|
||||||
|
auto < = cu.get_line_table();
|
||||||
|
auto it = lt.find_address(rip);
|
||||||
|
if (it == lt.end()) {
|
||||||
|
printf("ADDR NOT FOUND\n");
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
|
AddrInfo *ai = (AddrInfo *)malloc(sizeof(*ai));
|
||||||
|
ai->addr = rip;
|
||||||
|
ai->line = it->line;
|
||||||
|
ai->file = (const char*)malloc(strlen(it->file->path.c_str())+1);
|
||||||
|
strcpy((char*)ai->file, it->file->path.c_str());
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("NO CUS\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUGUS_EXTERNC void libelfin_wrap_free_info(AddrInfo *ai)
|
||||||
|
{
|
||||||
|
free((void*)ai->file);
|
||||||
|
free((void*)ai);
|
||||||
|
}
|
||||||
|
|
||||||
25
libelfin_wrap.h
Normal file
25
libelfin_wrap.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#ifndef LIBELFIN_WRAP_H_
|
||||||
|
#define LIBELFIN_WRAP_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
# define DEBUGUS_EXTERNC extern "C"
|
||||||
|
#else
|
||||||
|
# define DEBUGUS_EXTERNC
|
||||||
|
#endif // __cplusplus
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ssize_t line;
|
||||||
|
const char *file;
|
||||||
|
uint64_t addr;
|
||||||
|
} AddrInfo;
|
||||||
|
|
||||||
|
DEBUGUS_EXTERNC void libelfin_wrap_init(int fd);
|
||||||
|
DEBUGUS_EXTERNC AddrInfo *libelfin_wrap_info_from_rip(uint64_t rip);
|
||||||
|
DEBUGUS_EXTERNC void libelfin_wrap_free_info(AddrInfo *ai);
|
||||||
|
|
||||||
|
#endif // LIBELFIN_WRAP_H_
|
||||||
Reference in New Issue
Block a user