#include "config.h"
#include <stdio.h>
#ifdef HAVE_MALLOC_H
#include <malloc.h>
#endif
#ifdef HAVE_STDDEF_H
#include <stddef.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#ifdef HAVE_ELF_H
#include <elf.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#if 0
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#endif
#include "dwarf_incl.h"
#include "dwarf_alloc.h"
#include "dwarf_error.h"
#include "dwarf_util.h"
#include "dwarfstring.h"
#include "dwarf_debuglink.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#define MINBUFLEN 1000
#define TRUE 1
#define FALSE 0
#ifdef HAVE_UNUSED_ATTRIBUTE
#define UNUSEDARG __attribute__ ((unused))
#else
#define UNUSEDARG
#endif
#if _WIN32
#define NULL_DEVICE_NAME "NUL"
#else
#define NULL_DEVICE_NAME "/dev/null"
#endif
#ifdef WORDS_BIGENDIAN
#define ASNAR(func,t,s) \
do { \
unsigned tbyte = sizeof(t) - sizeof(s); \
t = 0; \
func(((char *)&t)+tbyte ,&s[0],sizeof(s)); \
} while (0)
#else
#define ASNAR(func,t,s) \
do { \
t = 0; \
func(&t,&s[0],sizeof(s)); \
} while (0)
#endif
static int
extract_buildid(Dwarf_Debug dbg,
struct Dwarf_Section_s * pbuildid,
unsigned *type_returned,
char **owner_name_returned,
unsigned char **build_id_returned,
unsigned *build_id_length_returned,
Dwarf_Error *error);
struct joins_s {
char * js_fullpath;
dwarfstring js_dirname;
dwarfstring js_basepath;
dwarfstring js_basename;
dwarfstring js_cwd;
dwarfstring js_originalfullpath;
dwarfstring js_tmp;
dwarfstring js_tmp2;
dwarfstring js_tmpdeb;
dwarfstring js_tmp3;
dwarfstring js_buildid;
dwarfstring js_buildid_filename;
};
#if 0
int
_dwarf_check_string_valid(
void *areaptr,
void *strptr,
void *areaendptr,
int suggested_error,
int *errcode)
{
Dwarf_Small *start = areaptr;
Dwarf_Small *p = strptr;
Dwarf_Small *end = areaendptr;
ptrdiff_t diff = 0;
if (p < start) {
diff = start - p;
#ifdef TESTING
printf("Error string start pointer error: loc %"
DW_PR_DSs
" bytes before available area \n",(Dwarf_Signed)diff);
#endif
*errcode = suggested_error;
return DW_DLV_ERROR;
}
if (p >= end) {
diff = p - start;
#ifdef TESTING
printf("Error string end pointer error, not terminated %"
" before end of area. Length: "
DW_PR_DSs "\n",(Dwarf_Signed)diff);
#endif
*errcode = suggested_error;
return DW_DLV_ERROR;
}
while (p < end) {
if (*p == 0) {
return DW_DLV_OK;
}
++p;
}
diff = p - start;
#ifdef TESTING
printf("Error string not terminated error: not ended after %"
DW_PR_DSs " bytes (past end of available bytes)\n",
(Dwarf_Signed)diff);
#endif
*errcode = DW_DLE_STRING_NOT_TERMINATED;
return DW_DLV_ERROR;
}
#endif
#if 0
static int
does_file_exist(char *f)
{
int fd = 0;
fd = open(f,O_RDONLY|O_BINARY);
if (fd < 0) {
return DW_DLV_NO_ENTRY;
}
close(fd);
return DW_DLV_OK;
}
#endif
static void
construct_js(struct joins_s * js)
{
memset(js,0,sizeof(struct joins_s));
dwarfstring_constructor(&js->js_basename);
dwarfstring_constructor(&js->js_dirname);
dwarfstring_constructor(&js->js_basepath);
dwarfstring_constructor(&js->js_cwd);
dwarfstring_constructor(&js->js_originalfullpath);
dwarfstring_constructor(&js->js_tmp);
dwarfstring_constructor(&js->js_tmp2);
dwarfstring_constructor(&js->js_tmpdeb);
dwarfstring_constructor(&js->js_tmp3);
dwarfstring_constructor(&js->js_buildid);
dwarfstring_constructor(&js->js_buildid_filename);
}
static void
destruct_js(struct joins_s * js)
{
dwarfstring_destructor(&js->js_dirname);
dwarfstring_destructor(&js->js_basepath);
dwarfstring_destructor(&js->js_basename);
dwarfstring_destructor(&js->js_cwd);
dwarfstring_destructor(&js->js_originalfullpath);
dwarfstring_destructor(&js->js_tmp);
dwarfstring_destructor(&js->js_tmp2);
dwarfstring_destructor(&js->js_tmpdeb);
dwarfstring_destructor(&js->js_tmp3);
dwarfstring_destructor(&js->js_buildid);
dwarfstring_destructor(&js->js_buildid_filename);
}
static char joinchar = '/';
static char* joinstr = "/";
int
_dwarf_pathjoinl(dwarfstring *target,dwarfstring * input)
{
char *inputs = dwarfstring_string(input);
char *targ = dwarfstring_string(target);
size_t targlen = 0;
if (!dwarfstring_strlen(target)) {
dwarfstring_append(target,dwarfstring_string(input));
return DW_DLV_OK;
}
targlen = dwarfstring_strlen(target);
targ = dwarfstring_string(target);
if (targ[targlen-1] != joinchar) {
if (*inputs != joinchar) {
dwarfstring_append(target,joinstr);
dwarfstring_append(target,inputs);
} else {
dwarfstring_append(target,inputs);
}
} else {
if (*inputs != joinchar) {
dwarfstring_append(target,inputs);
} else {
dwarfstring_append(target,inputs+1);
}
}
return DW_DLV_OK;
}
static size_t
mydirlen(char *s)
{
char *cp = 0;
char *lastjoinchar = 0;
size_t count =0;
for(cp = s ; *cp ; ++cp,++count) {
if (*cp == joinchar) {
lastjoinchar = cp;
}
}
if (lastjoinchar) {
ptrdiff_t diff = lastjoinchar - s;
return (size_t)(diff+1);
}
return 0;
}
struct dwarfstring_list_s {
dwarfstring dl_string;
struct dwarfstring_list_s *dl_next;
};
static void
dwarfstring_list_constructor(struct dwarfstring_list_s *l)
{
dwarfstring_constructor(&l->dl_string);
l->dl_next = 0;
}
static int
dwarfstring_list_add_new(struct dwarfstring_list_s * base_entry,
struct dwarfstring_list_s *prev,
dwarfstring * input,
struct dwarfstring_list_s ** new_out,
int *errcode)
{
struct dwarfstring_list_s *next = 0;
if(prev) {
next = ( struct dwarfstring_list_s *)
malloc(sizeof(struct dwarfstring_list_s));
if (!next) {
*errcode = DW_DLE_ALLOC_FAIL;
return DW_DLV_ERROR;
}
dwarfstring_list_constructor(next);
} else {
next = base_entry;
}
dwarfstring_append(&next->dl_string,
dwarfstring_string(input));
if (prev) {
prev->dl_next = next;
}
*new_out = next;
return DW_DLV_OK;
}
static void
dwarfstring_list_destructor(struct dwarfstring_list_s *l)
{
struct dwarfstring_list_s *curl = l;
struct dwarfstring_list_s *nextl = l;
nextl = curl->dl_next;
dwarfstring_destructor(&curl->dl_string);
curl->dl_next = 0;
curl = nextl;
for( ; curl ; curl = nextl) {
nextl = curl->dl_next;
dwarfstring_destructor(&curl->dl_string);
curl->dl_next = 0;
free(curl);
}
}
static void
build_buildid_filename(dwarfstring *target,
unsigned buildid_length,
unsigned char *buildid)
{
dwarfstring tmp;
unsigned bu = 0;
unsigned char *cp = 0;
dwarfstring_constructor(&tmp);
cp = buildid;
for (bu = 0; bu < buildid_length; ++bu ,++cp) {
dwarfstring_append_printf_u(&tmp, "%02x",*cp);
if (bu == 0) {
dwarfstring_append(&tmp,"/");
}
}
dwarfstring_append(&tmp,".debug");
_dwarf_pathjoinl(target,&tmp);
dwarfstring_destructor(&tmp);
return;
}
#if 0
static void
dump_bytes(const char *msg,unsigned char * start, unsigned len)
{
Dwarf_Small *end = start + len;
Dwarf_Small *cur = start;
printf("%s (0x%lx) ",msg,(unsigned long)start);
for (; cur < end; cur++) {
printf("%02x", *cur);
}
printf("\n");
}
#endif
int _dwarf_construct_linkedto_path(
char **global_prefixes_in,
unsigned length_global_prefixes_in,
char *pathname_in,
char *link_string_in,
dwarfstring * link_string_fullpath_out,
UNUSEDARG unsigned char *crc_in,
unsigned char *buildid,
unsigned buildid_length,
char ***paths_out,
unsigned *paths_out_length,
int *errcode)
{
char * depath = pathname_in;
int res = 0;
struct joins_s joind;
size_t dirnamelen = 0;
struct dwarfstring_list_s base_dwlist;
struct dwarfstring_list_s *last_entry = 0;
unsigned global_prefix_number = 0;
dwarfstring_list_constructor(&base_dwlist);
construct_js(&joind);
build_buildid_filename(&joind.js_buildid_filename,
buildid_length, buildid);
dirnamelen = mydirlen(depath);
if (dirnamelen) {
dwarfstring_append_length(&joind.js_dirname,
depath,dirnamelen);
}
dwarfstring_append(&joind.js_basepath,depath+dirnamelen);
dwarfstring_append(&joind.js_basename,link_string_in);
if (depath[0] != joinchar) {
char buffer[2000];
#ifdef TESTING
buffer[0] = 0;
strcpy(buffer,"/fake/dir/path");
#else
unsigned buflen= sizeof(buffer);
char *wdret = 0;
buffer[0] = 0;
wdret = getcwd(buffer,buflen);
if (!wdret) {
printf("getcwd() issue. Do nothing. "
" line %d %s\n",__LINE__,__FILE__);
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
*errcode = DW_DLE_ALLOC_FAIL;
return DW_DLV_ERROR;
}
#endif
dwarfstring_append(&joind.js_cwd,buffer);
buffer[0] = 0;
}
{
dwarfstring_append(&joind.js_originalfullpath,
dwarfstring_string(&joind.js_cwd));
_dwarf_pathjoinl(&joind.js_originalfullpath,
&joind.js_dirname);
_dwarf_pathjoinl(&joind.js_originalfullpath,
&joind.js_basepath);
#ifdef TESTING
printf("originalfullpath : %s\n",
dwarfstring_string(&joind.js_originalfullpath));
#endif
}
{
res = _dwarf_pathjoinl(&joind.js_cwd,
&joind.js_dirname);
}
for (global_prefix_number = 0;
buildid_length &&
(global_prefix_number < length_global_prefixes_in);
++global_prefix_number) {
char * prefix = 0;
prefix = global_prefixes_in[global_prefix_number];
dwarfstring_reset(&joind.js_buildid);
dwarfstring_append(&joind.js_buildid,prefix);
_dwarf_pathjoinl(&joind.js_buildid,
&joind.js_buildid_filename);
if (!strcmp(dwarfstring_string(&joind.js_originalfullpath),
dwarfstring_string(&joind.js_buildid))) {
#ifdef TESTING
printf("duplicated output string %s\n",
dwarfstring_string(&joind.js_buildid));
#endif
} else {
struct dwarfstring_list_s *now_last = 0;
res = dwarfstring_list_add_new(
&base_dwlist,
last_entry,&joind.js_buildid,
&now_last,errcode);
if(res != DW_DLV_OK) {
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
return res;
}
last_entry = now_last;
}
}
if (link_string_in) {
{
dwarfstring_reset(&joind.js_tmp);
dwarfstring_append(&joind.js_tmp,
dwarfstring_string(&joind.js_cwd));
res = _dwarf_pathjoinl(&joind.js_tmp,&joind.js_basename);
dwarfstring_append(link_string_fullpath_out,
dwarfstring_string(&joind.js_tmp));
if (!strcmp(dwarfstring_string(&joind.js_originalfullpath),
dwarfstring_string(&joind.js_tmp))) {
#ifdef TESTING
printf("duplicated output string %s\n",
dwarfstring_string(&joind.js_tmp));
#endif
} else if (res == DW_DLV_OK) {
struct dwarfstring_list_s *now_last = 0;
res = dwarfstring_list_add_new(
&base_dwlist,
last_entry,&joind.js_tmp,
&now_last,errcode);
if(res != DW_DLV_OK) {
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
return res;
}
last_entry = now_last;
}
}
{
dwarfstring_reset(&joind.js_tmp2);
dwarfstring_reset(&joind.js_tmpdeb);
dwarfstring_append(&joind.js_tmp2,
dwarfstring_string(&joind.js_cwd));
dwarfstring_append(&joind.js_tmpdeb,".debug");
res = _dwarf_pathjoinl(&joind.js_tmp2,&joind.js_tmpdeb);
if (res == DW_DLV_OK) {
res = _dwarf_pathjoinl(&joind.js_tmp2,
&joind.js_basename);
if (!strcmp(dwarfstring_string(
&joind.js_originalfullpath),
dwarfstring_string(&joind.js_tmp2))) {
#ifdef TESTING
printf("duplicated output string %s\n",
dwarfstring_string(&joind.js_tmp2));
#endif
} else if(res == DW_DLV_OK) {
struct dwarfstring_list_s *now_last = 0;
res = dwarfstring_list_add_new(
&base_dwlist,
last_entry,&joind.js_tmp2,
&now_last,errcode);
if(res != DW_DLV_OK) {
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
return res;
}
last_entry = now_last;
}
}
}
for (global_prefix_number = 0;
global_prefix_number < length_global_prefixes_in;
++global_prefix_number) {
char * prefix = global_prefixes_in[global_prefix_number];
dwarfstring_reset(&joind.js_tmp3);
dwarfstring_append(&joind.js_tmp3, prefix);
res = _dwarf_pathjoinl(&joind.js_tmp3, &joind.js_cwd);
if (res == DW_DLV_OK) {
res = _dwarf_pathjoinl(&joind.js_tmp3,
&joind.js_basename);
if (!strcmp(dwarfstring_string(
&joind.js_originalfullpath),
dwarfstring_string(&joind.js_tmp3))) {
#ifdef TESTING
printf("duplicated output string %s\n",
dwarfstring_string(&joind.js_tmp3));
#endif
} else if (res == DW_DLV_OK) {
struct dwarfstring_list_s *now_last = 0;
res = dwarfstring_list_add_new(
&base_dwlist,
last_entry,&joind.js_tmp3,
&now_last,errcode);
if(res != DW_DLV_OK) {
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
return res;
}
last_entry = now_last;
}
}
}
}
{
struct dwarfstring_list_s *cur = 0;
char **resultfullstring = 0;
unsigned long count = 0;
unsigned long pointerarraysize = 0;
unsigned long sumstringlengths = 0;
unsigned long totalareasize = 0;
unsigned long setptrindex = 0;
unsigned long setstrindex = 0;
cur = &base_dwlist;
for ( ; cur ; cur = cur->dl_next) {
++count;
pointerarraysize += sizeof(void *);
sumstringlengths +=
dwarfstring_strlen(&cur->dl_string) +1;
}
pointerarraysize += sizeof(void *);
totalareasize = pointerarraysize + sumstringlengths +8;
resultfullstring = (char **)malloc(totalareasize);
setstrindex = pointerarraysize;
if(!resultfullstring) {
#ifdef TESTING
printf("Malloc fail making final paths. Length %lu"
" bytes.\n",totalareasize);
#endif
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
*errcode = DW_DLE_ALLOC_FAIL;
return DW_DLV_ERROR;
}
memset(resultfullstring,0,totalareasize);
cur = &base_dwlist;
for ( ; cur ; cur = cur->dl_next,++setptrindex) {
char **iptr = (char **)((char *)resultfullstring +
setptrindex*sizeof(void *));
char *sptr = (char*)resultfullstring + setstrindex;
strcpy(sptr,dwarfstring_string(&cur->dl_string));
setstrindex += dwarfstring_strlen(&cur->dl_string)+1;
*iptr = sptr;
}
*paths_out = resultfullstring;
*paths_out_length = count;
}
dwarfstring_list_destructor(&base_dwlist);
destruct_js(&joind);
return DW_DLV_OK;
}
static int
extract_debuglink(Dwarf_Debug dbg,
struct Dwarf_Section_s * pdebuglink,
char ** name_returned,
unsigned char ** crc_returned,
Dwarf_Error *error)
{
Dwarf_Small *ptr = 0;
Dwarf_Small *endptr = 0;
unsigned namelen = 0;
unsigned m = 0;
unsigned incr = 0;
Dwarf_Small *crcptr = 0;
int res = DW_DLV_ERROR;
Dwarf_Unsigned secsize = 0;
if (!pdebuglink->dss_data) {
res = _dwarf_load_section(dbg, pdebuglink,error);
if (res != DW_DLV_OK) {
return res;
}
}
secsize = pdebuglink->dss_size;
ptr = pdebuglink->dss_data;
endptr = ptr + secsize;
res = _dwarf_check_string_valid(dbg,ptr,
ptr, endptr, DW_DLE_FORM_STRING_BAD_STRING,
error);
if ( res != DW_DLV_OK) {
return res;
}
namelen = (unsigned)strlen((const char*)ptr);
m = (namelen+1) %4;
if (m) {
incr = 4 - m;
}
crcptr = (unsigned char *)ptr +namelen +1 +incr;
if ((crcptr +4) != (unsigned char*)endptr) {
_dwarf_error(dbg,error,DW_DLE_CORRUPT_GNU_DEBUGLINK);
return DW_DLV_ERROR;
}
*name_returned = (char *)ptr;
*crc_returned = crcptr;
return DW_DLV_OK;
}
struct buildid_s {
char bu_ownernamesize[4];
char bu_buildidsize[4];
char bu_type[4];
char bu_owner[1];
};
static int
extract_buildid(Dwarf_Debug dbg,
struct Dwarf_Section_s * pbuildid,
unsigned * type_returned,
char **owner_name_returned,
unsigned char **build_id_returned,
unsigned * build_id_length_returned,
Dwarf_Error *error)
{
Dwarf_Small * ptr = 0;
Dwarf_Small * endptr = 0;
int res = DW_DLV_ERROR;
struct buildid_s *bu = 0;
Dwarf_Unsigned namesize = 0;
Dwarf_Unsigned descrsize = 0;
Dwarf_Unsigned type = 0;
Dwarf_Unsigned finalsize;
Dwarf_Unsigned secsize = 0;
if (!pbuildid->dss_data) {
res = _dwarf_load_section(dbg, pbuildid,error);
if (res != DW_DLV_OK) {
return res;
}
}
secsize = pbuildid->dss_size;
ptr = pbuildid->dss_data;
if (secsize < sizeof(struct buildid_s)) {
#ifdef TESTING
printf("ERROR section .note.gnu.build-id too small: "
" section length: 0x%" DW_PR_DUx
" minimum struct size 0x%" DW_PR_DUx "\n",
secsize,(Dwarf_Unsigned) sizeof(struct buildid_s));
#endif
_dwarf_error(dbg,error,DW_DLE_CORRUPT_NOTE_GNU_DEBUGID);
return DW_DLV_ERROR;
}
endptr = ptr + secsize;
bu = (struct buildid_s *)ptr;
ASNAR(dbg->de_copy_word,namesize, bu->bu_ownernamesize);
ASNAR(dbg->de_copy_word,descrsize,bu->bu_buildidsize);
ASNAR(dbg->de_copy_word,type, bu->bu_type);
if (descrsize != 20) {
_dwarf_error(dbg,error,DW_DLE_CORRUPT_NOTE_GNU_DEBUGID);
return DW_DLV_ERROR;
}
res = _dwarf_check_string_valid(dbg,
(Dwarf_Small *)&bu->bu_owner[0],
(Dwarf_Small *)&bu->bu_owner[0],
endptr,
DW_DLE_CORRUPT_GNU_DEBUGID_STRING,
error);
if ( res != DW_DLV_OK) {
return res;
}
if ((strlen(bu->bu_owner) +1) != namesize) {
_dwarf_error(dbg,error, DW_DLE_CORRUPT_GNU_DEBUGID_STRING);
return res;
}
finalsize = sizeof(struct buildid_s)-1 + namesize + descrsize;
if (finalsize > secsize) {
_dwarf_error(dbg,error, DW_DLE_CORRUPT_GNU_DEBUGID_SIZE);
return DW_DLV_ERROR;
}
*type_returned = type;
*owner_name_returned = &bu->bu_owner[0];
*build_id_length_returned = descrsize;
*build_id_returned = (unsigned char *)ptr +
sizeof(struct buildid_s)-1 + namesize;
return DW_DLV_OK;
}
int dwarf_gnu_debuglink(Dwarf_Debug dbg,
char ** debuglink_path_returned,
unsigned char ** crc_returned,
char ** debuglink_fullpath_returned,
unsigned * debuglink_fullpath_length_returned,
unsigned * buildid_type_returned ,
char ** buildid_owner_name_returned,
unsigned char ** buildid_returned,
unsigned * buildid_length_returned,
char *** paths_returned,
unsigned * paths_count_returned,
Dwarf_Error* error)
{
dwarfstring debuglink_fullpath;
int linkres = DW_DLV_ERROR;
int res = DW_DLV_ERROR;
char * pathname = 0;
int buildidres = 0;
int errcode = 0;
struct Dwarf_Section_s * pdebuglink = 0;
struct Dwarf_Section_s * pbuildid = 0;
if(!dbg) {
_dwarf_error(dbg,error,DW_DLE_DBG_NULL);
return DW_DLV_ERROR;
}
if (dbg->de_gnu_debuglink.dss_size) {
pdebuglink = &dbg->de_gnu_debuglink;
}
if (dbg->de_note_gnu_buildid.dss_size) {
pbuildid = &dbg->de_note_gnu_buildid;
}
if (!pdebuglink && !pbuildid) {
return DW_DLV_NO_ENTRY;
}
if (pdebuglink) {
linkres = extract_debuglink(dbg,
pdebuglink,
debuglink_path_returned,
crc_returned,
error);
if (linkres == DW_DLV_ERROR) {
return linkres;
}
}
if (pbuildid) {
buildidres = extract_buildid(dbg,
pbuildid,
buildid_type_returned,
buildid_owner_name_returned,
buildid_returned,
buildid_length_returned,
error);
if (buildidres == DW_DLV_ERROR) {
return buildidres;
}
}
dwarfstring_constructor(&debuglink_fullpath);
pathname = (char *)dbg->de_path;
if (pathname && paths_returned) {
res = _dwarf_construct_linkedto_path(
(char **)dbg->de_gnu_global_paths,
dbg->de_gnu_global_path_count,
pathname,
*debuglink_path_returned,
&debuglink_fullpath,
*crc_returned,
*buildid_returned,
*buildid_length_returned,
paths_returned,
paths_count_returned,
&errcode);
if(res != DW_DLV_OK) {
dwarfstring_destructor(&debuglink_fullpath);
return res;
}
if (dwarfstring_strlen(&debuglink_fullpath)) {
*debuglink_fullpath_returned =
strdup(dwarfstring_string(&debuglink_fullpath));
*debuglink_fullpath_length_returned =
dwarfstring_strlen(&debuglink_fullpath);
}
} else if (paths_count_returned) {
*paths_count_returned = 0;
}
dwarfstring_destructor(&debuglink_fullpath);
return DW_DLV_OK;
}
int
dwarf_add_debuglink_global_path(Dwarf_Debug dbg,
const char *pathname,
Dwarf_Error *error)
{
unsigned glpath_count_in = 0;
unsigned glpath_count_out = 0;
const char **glpaths = 0;
const char * path1 = 0;
glpath_count_in = dbg->de_gnu_global_path_count;
glpath_count_out = glpath_count_in+1;
glpaths = (const char **)malloc(sizeof(char *)*
glpath_count_out);
if (!glpaths) {
_dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
if (glpath_count_in) {
memcpy(glpaths, dbg->de_gnu_global_paths,
sizeof(char *)*glpath_count_in);
}
path1 = strdup(pathname);
if (!path1) {
free(glpaths);
_dwarf_error(dbg,error,DW_DLE_ALLOC_FAIL);
return DW_DLV_ERROR;
}
free((char *)dbg->de_gnu_global_paths);
glpaths[glpath_count_in] = path1;
dbg->de_gnu_global_paths = (const char **)glpaths;
dbg->de_gnu_global_path_count = glpath_count_out;
return DW_DLV_OK;
}