#include "config.h"
#ifdef HAVE_LIBELF_H
#include <libelf.h>
#else
#ifdef HAVE_LIBELF_LIBELF_H
#include <libelf/libelf.h>
#endif
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#elif defined(_WIN32) && defined(_MSC_VER)
#include <io.h>
#endif
#include "dwarf_incl.h"
#include "dwarf_error.h"
#include "dwarf_object_detector.h"
#include "dwarf_elf_access.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define DWARF_DBG_ERROR(dbg,errval,retval) \
_dwarf_error(dbg, error, errval); return(retval);
#define FALSE 0
#define TRUE 1
int
dwarf_init(int fd,
Dwarf_Unsigned access,
Dwarf_Handler errhand,
Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error)
{
return dwarf_init_b(fd,access, DW_GROUPNUMBER_ANY,
errhand,errarg,ret_dbg,error);
}
static int
open_a_file(const char * name)
{
int fd = -1;
#if HAVE_ELF_OPEN
fd = elf_open(name, O_RDONLY | O_BINARY);
#else
fd = open(name, O_RDONLY | O_BINARY);
#endif
return fd;
}
static int
set_global_paths_init(Dwarf_Debug dbg, Dwarf_Error* error)
{
int res = 0;
res = dwarf_add_debuglink_global_path(dbg,
"/usr/lib/debug",error);
return res;
}
int dwarf_init_path(const char *path,
char *true_path_out_buffer,
unsigned true_path_bufferlen,
Dwarf_Unsigned access,
unsigned groupnumber,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug* ret_dbg,
UNUSEDARG const char * reserved1,
UNUSEDARG Dwarf_Unsigned reserved2,
UNUSEDARG Dwarf_Unsigned * reserved3,
Dwarf_Error* error)
{
unsigned ftype = 0;
unsigned endian = 0;
unsigned offsetsize = 0;
Dwarf_Unsigned filesize = 0;
int res = 0;
int errcode = 0;
int fd = -1;
Dwarf_Debug dbg = 0;
char *file_path = 0;
if (!ret_dbg) {
DWARF_DBG_ERROR(NULL,DW_DLE_DWARF_INIT_DBG_NULL,DW_DLV_ERROR);
}
res = dwarf_object_detector_path(path,
true_path_out_buffer,
true_path_bufferlen,
&ftype,&endian,&offsetsize,&filesize,&errcode);
if (res == DW_DLV_NO_ENTRY) {
return res;
}
if (res == DW_DLV_ERROR) {
DWARF_DBG_ERROR(NULL, errcode, DW_DLV_ERROR);
}
if (true_path_out_buffer) {
file_path = true_path_out_buffer;
fd = open_a_file(true_path_out_buffer);
} else {
file_path = (char *)path;
fd = open_a_file(path);
}
if(fd == -1) {
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_UNAVAILABLE,
DW_DLV_ERROR);
}
switch(ftype) {
case DW_FTYPE_ELF: {
res = _dwarf_elf_nlsetup(fd,
file_path,
ftype,endian,offsetsize,filesize,
access,groupnumber,errhand,errarg,&dbg,error);
if (res != DW_DLV_OK) {
*ret_dbg = dbg;
close(fd);
return res;
}
dbg->de_path = strdup(file_path);
dbg->de_fd = fd;
dbg->de_owns_fd = TRUE;
res = set_global_paths_init(dbg,error);
*ret_dbg = dbg;
return res;
}
case DW_FTYPE_MACH_O: {
res = _dwarf_macho_setup(fd,
file_path,
ftype,endian,offsetsize,filesize,
access,groupnumber,errhand,errarg,&dbg,error);
if (res != DW_DLV_OK) {
close(fd);
*ret_dbg = dbg;
return res;
}
dbg->de_path = strdup(file_path);
dbg->de_fd = fd;
dbg->de_owns_fd = TRUE;
set_global_paths_init(dbg,error);
*ret_dbg = dbg;
return res;
}
case DW_FTYPE_PE: {
res = _dwarf_pe_setup(fd,
file_path,
ftype,endian,offsetsize,filesize,
access,groupnumber,errhand,errarg,&dbg,error);
if (res != DW_DLV_OK) {
close(fd);
*ret_dbg = dbg;
}
dbg->de_path = strdup(file_path);
dbg->de_fd = fd;
dbg->de_owns_fd = TRUE;
set_global_paths_init(dbg,error);
*ret_dbg = dbg;
return res;
}
default:
close(fd);
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR);
}
return DW_DLV_NO_ENTRY;
}
int
dwarf_init_b(int fd,
Dwarf_Unsigned access,
unsigned group_number,
Dwarf_Handler errhand,
Dwarf_Ptr errarg,
Dwarf_Debug * ret_dbg,
Dwarf_Error * error)
{
unsigned ftype = 0;
unsigned endian = 0;
unsigned offsetsize = 0;
Dwarf_Unsigned filesize = 0;
int res = 0;
int errcode = 0;
if (!ret_dbg) {
DWARF_DBG_ERROR(NULL,DW_DLE_DWARF_INIT_DBG_NULL,DW_DLV_ERROR);
}
res = dwarf_object_detector_fd(fd, &ftype,
&endian,&offsetsize,&filesize,&errcode);
if (res == DW_DLV_NO_ENTRY) {
return res;
} else if (res == DW_DLV_ERROR) {
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR);
}
switch(ftype) {
case DW_FTYPE_ELF: {
int res2 = 0;
res2 = _dwarf_elf_nlsetup(fd,"",
ftype,endian,offsetsize,filesize,
access,group_number,errhand,errarg,ret_dbg,error);
if (res2 != DW_DLV_OK) {
return res2;
}
set_global_paths_init(*ret_dbg,error);
return res2;
}
case DW_FTYPE_MACH_O: {
int resm = 0;
resm = _dwarf_macho_setup(fd,"",
ftype,endian,offsetsize,filesize,
access,group_number,errhand,errarg,ret_dbg,error);
if (resm != DW_DLV_OK) {
return resm;
}
set_global_paths_init(*ret_dbg,error);
return resm;
}
case DW_FTYPE_PE: {
int resp = 0;
resp = _dwarf_pe_setup(fd,
"",
ftype,endian,offsetsize,filesize,
access,group_number,errhand,errarg,ret_dbg,error);
if (resp != DW_DLV_OK) {
return resp;
}
set_global_paths_init(*ret_dbg,error);
return resp;
}
}
DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR);
return res;
}
int
dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error)
{
if(!dbg) {
DWARF_DBG_ERROR(NULL, DW_DLE_DBG_NULL, DW_DLV_ERROR);
}
if (dbg->de_obj_file) {
char otype = *(char *)(dbg->de_obj_file->object);
switch(otype) {
case 'E':
#ifdef DWARF_WITH_LIBELF
dwarf_elf_object_access_finish(dbg->de_obj_file);
#endif
break;
case 'F':
_dwarf_destruct_elf_nlaccess(dbg->de_obj_file);
break;
case 'M':
_dwarf_destruct_macho_access(dbg->de_obj_file);
break;
case 'P':
_dwarf_destruct_pe_access(dbg->de_obj_file);
break;
default:
break;
}
}
if (dbg->de_owns_fd) {
close(dbg->de_fd);
dbg->de_owns_fd = FALSE;
}
free((void *)dbg->de_path);
dbg->de_path = 0;
return dwarf_object_finish(dbg, error);
}
int
dwarf_set_tied_dbg(Dwarf_Debug dbg, Dwarf_Debug tieddbg,Dwarf_Error*error)
{
if(!dbg) {
DWARF_DBG_ERROR(NULL, DW_DLE_DBG_NULL, DW_DLV_ERROR);
}
dbg->de_tied_data.td_tied_object = tieddbg;
if (tieddbg) {
tieddbg->de_tied_data.td_is_tied_object = TRUE;
}
return DW_DLV_OK;
}
int
dwarf_get_tied_dbg(Dwarf_Debug dbg, Dwarf_Debug *tieddbg_out,
UNUSEDARG Dwarf_Error*error)
{
*tieddbg_out = dbg->de_tied_data.td_tied_object;
return DW_DLV_OK;
}