12
I am writing a tool which uses libbfd and libopcodes in x86-32 and x86-64 Linux to perform disassembly. The problem is that whilst I am able to get libopcodes to disassemble, I am unable to get any instruction information. For the purposes of demonstration, I have made a minimal example which reproduces my issue. The program should disassemble itself from entry point to the first RET/RETQ.
The code is a bit hacked up with globals and error checking has been omitted for brevity, etc. but should illustrate the issue clearly.
#include <bfd.h>
#include <dis-asm.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <libiberty.h>
/*
* Holds state for BFD and libopcodes.
*/
bfd * abfd = NULL;
disassemble_info dinfo = {0};
/*
* Temporary hack to signal when disassembling should stop.
*/
static bool stop_disassembling = FALSE;
/*
* Gets path to currently running executable.
*/
bool get_target_path(char * target_path, size_t size)
{
char * path;
ssize_t len;
pid_t pid = getpid();
sprintf(target_path, "/proc/%d/exe", (int)pid );
path = strdup(target_path);
len = readlink(path, target_path, size);
target_path[len] = '\0';
free(path);
return TRUE;
}
/*
* libopcodes appends spaces on the end of some instructions so for
* comparisons, we want to strip those first.
*/
void strip_tail(char * str, unsigned int size)
{
int i;
for(i = 0; i < size; i++) {
if(!isgraph(str[i])) {
str[i] = '\0';
break;
}
}
}
/*
* Checks whether the current instruction will cause the control flow to not
* proceed to the linearly subsequent instruction (e.g. ret, jmp, etc.)
*/
bool breaks_control_flow(char * str)
{
if(abfd-