static void get_debug_info(Addr instr_addr, Char file[FILE_LEN],
Char fn[FN_LEN], Int* line)
{
- Bool found_file_line = VG_(get_filename_linenum)(instr_addr, file,
- FILE_LEN, line);
+ Bool found_file_line = VG_(get_filename_linenum)(
+ instr_addr,
+ file, FILE_LEN,
+ NULL, 0, NULL,
+ line
+ );
Bool found_fn = VG_(get_fnname)(instr_addr, fn, FN_LEN);
if (!found_file_line) {
UShort size:LOC_SIZE_BITS; /* byte size; we catch overflows of this */
UInt lineno:LINENO_BITS; /* source line number, or zero */
/* Word 3 */
- Char* filename; /* source filename */
+ Char* filename; /* source filename */
+ /* Word 4 */
+ Char* dirname; /* source directory name */
}
RiLoc;
Char *VG_(addStr) ( SegInfo* si, Char* str, Int len );
void VG_(addScopeInfo) ( SegInfo* si, Addr this, Addr next, Scope *scope);
-void VG_(addLineInfo) ( SegInfo* si, Char* filename, Addr this, Addr next, Int lineno, Int entry);
+void VG_(addLineInfo) ( SegInfo* si,
+ Char* filename,
+ Char* dirname, /* NULL is allowable */
+ Addr this, Addr next, Int lineno, Int entry);
void VG_(addCfiSI) ( SegInfo* si, CfiSI* cfisi );
/* Non-fatal -- use vg_panic if terminal. */
if (line.addr != 0) {
/* finish off previous line */
- VG_(addLineInfo)(si, file.name, line.addr,
+ VG_(addLineInfo)(si, file.name, NULL, line.addr,
addr, line.no + line.ovf * LINENO_OVERFLOW, i);
}
if (line.addr != 0) {
/* there was a previous */
- VG_(addLineInfo)(si, file.name, line.addr,
+ VG_(addLineInfo)(si, file.name, NULL, line.addr,
addr, line.no + line.ovf * LINENO_OVERFLOW, i);
}
}
if (line.addr) {
- VG_(addLineInfo)(si, file.name, line.addr,
+ VG_(addLineInfo)(si, file.name, NULL, line.addr,
addr, line.no + line.ovf * LINENO_OVERFLOW, i);
line.addr = 0;
}
void VG_(addLineInfo) ( SegInfo* si,
Char* filename,
+ Char* dirname, /* NULL == directory is unknown */
Addr this,
Addr next,
Int lineno,
Int entry /* only needed for debug printing */
- )
+ )
{
static const Bool debug = False;
RiLoc loc;
if (this == next) return;
if (debug)
- VG_(printf)(" src %s line %d %p-%p\n", filename, lineno, this, next);
+ VG_(printf)( " src %s %s line %d %p-%p\n",
+ dirname ? dirname : (Char*)"(unknown)",
+ filename, lineno, this, next );
/* Maximum sanity checking. Some versions of GNU as do a shabby
* job with stabs entries; if anything looks suspicious, revert to
loc.size = (UShort)size;
loc.lineno = lineno;
loc.filename = filename;
+ loc.dirname = dirname;
if (0) VG_(message)(Vg_DebugMsg,
"addLoc: addr %p, size %d, line %d, file %s",
return True;
}
-/* Map a code address to a (filename, line number) pair.
- Returns True if successful.
+/* Map a code address to a filename/line number/dir name info.
+ See prototype for detailed description of behaviour.
*/
-Bool VG_(get_filename_linenum)( Addr a,
- Char* filename, Int n_filename,
- UInt* lineno )
+Bool VG_(get_filename_linenum) ( Addr a,
+ /*OUT*/Char* filename, Int n_filename,
+ /*OUT*/Char* dirname, Int n_dirname,
+ /*OUT*/Bool* dirname_available,
+ /*OUT*/UInt* lineno )
{
SegInfo* si;
Int locno;
+
+ vg_assert( (dirname == NULL && dirname_available == NULL)
+ ||
+ (dirname != NULL && dirname_available != NULL) );
+
search_all_loctabs ( a, &si, &locno );
if (si == NULL)
return False;
VG_(strncpy_safely)(filename, si->loctab[locno].filename, n_filename);
*lineno = si->loctab[locno].lineno;
+ if (dirname) {
+ /* caller wants directory info too .. */
+ vg_assert(n_dirname > 0);
+ if (si->loctab[locno].dirname) {
+ /* .. and we have some */
+ *dirname_available = True;
+ VG_(strncpy_safely)(dirname, si->loctab[locno].dirname,
+ n_dirname);
+ } else {
+ /* .. but we don't have any */
+ *dirname_available = False;
+ *dirname = 0;
+ }
+ }
+
return True;
}
static Addr regaddr_from_tst(Int regno, ThreadArchState *arch)
{
#if defined(VGA_x86)
-/* This is the Intel register encoding -- integer regs. */
+ /* This is the Intel register encoding -- integer regs. */
# define R_STACK_PTR 4
# define R_FRAME_PTR 5
switch (regno) {
default: return 0;
}
#elif defined(VGA_amd64)
-/* This is the Intel register encoding -- integer regs. */
+ /* This is the AMD64 register encoding -- integer regs. */
# define R_STACK_PTR 7
# define R_FRAME_PTR 6
switch (regno) {
Char file[100];
Int line;
- if (!VG_(get_filename_linenum)(sr->addr, file, sizeof(file), &line))
+ if (!VG_(get_filename_linenum)(sr->addr, file, sizeof(file),
+ NULL, 0, NULL, &line))
file[0] = 0;
VG_(printf)("found scope range %p: eip=%p (%s:%d) size=%d scope=%p\n",
}
distance = 0;
- for(scope = si->scopetab[scopeidx].scope; scope != NULL; scope = scope->outer, distance++) {
+ for (scope = si->scopetab[scopeidx].scope;
+ scope != NULL;
+ scope = scope->outer, distance++) {
UInt i;
for(i = 0; i < scope->nsyms; i++) {
return list;
}
+
+# undef R_STACK_PTR
+# undef R_FRAME_PTR
+
#endif /* TEST */
/* Print into buf info on code address, function name and filename */
static UChar buf_fn[BUF_LEN];
static UChar buf_obj[BUF_LEN];
static UChar buf_srcloc[BUF_LEN];
+ static UChar buf_dirname[BUF_LEN];
+ Bool know_dirinfo = False;
Bool know_fnname = VG_(get_fnname) (eip, buf_fn, BUF_LEN);
Bool know_objname = VG_(get_objname)(eip, buf_obj, BUF_LEN);
- Bool know_srcloc = VG_(get_filename_linenum)(eip, buf_srcloc,
- BUF_LEN, &lineno);
-
+ Bool know_srcloc = VG_(get_filename_linenum)(
+ eip,
+ buf_srcloc, BUF_LEN,
+ buf_dirname, BUF_LEN, &know_dirinfo,
+ &lineno
+ );
if (VG_(clo_xml)) {
Bool human_readable = True;
APPEND("</fn>");
}
if (know_srcloc) {
+ if (know_dirinfo) {
+ APPEND(maybe_newline);
+ APPEND("<dir>");
+ APPEND(buf_dirname);
+ APPEND("</dir>");
+ }
APPEND(maybe_newline);
APPEND("<file>");
APPEND_ESC(buf_srcloc);
# undef APPEND
# undef APPEND_ESC
+# undef BUF_LEN
}
/* Returns True if OK. If not OK, *{ip,sp,fp}P are not changed. */
if (debug) {
Char file[100];
Int line;
- if (!VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
+ if (!VG_(get_filename_linenum)(eip, file, sizeof(file),
+ NULL, 0, NULL, &line))
file[0] = 0;
VG_(printf)("describing address %p for tid=%d @ %s:%d\n", addr, tid, file, line);
}
if (addr != found->valuep)
bprintf(describe_addr_addbuf, 0, "+%d", addr - found->valuep);
- if (VG_(get_filename_linenum)(eip, file, sizeof(file), &line))
+ if (VG_(get_filename_linenum)(eip, file, sizeof(file),
+ NULL, 0, NULL, &line))
bprintf(describe_addr_addbuf, 0, " at %s:%d", file, line, addr);
}
}
pp_state(extra->lasttouched.state),
unpackTLS(extra->lasttouched.tls)->tid);
- if (VG_(get_filename_linenum)(ip, file, sizeof(file), &line)) {
+ if (VG_(get_filename_linenum)(ip, file, sizeof(file),
+ NULL, 0, NULL, &line)) {
VG_(message)(Vg_UserMsg, " at %p: %y (%s:%u)",
ip, ip, file, line);
} else if (VG_(get_objname)(ip, file, sizeof(file))) {
extern Bool VG_(get_fnname_w_offset)
( Addr a, Char* fnname, Int n_fnname );
-/* This one is more efficient if getting both filename and line number,
- because the two lookups are done together. */
+/* This one is the most general. It gives filename, line number and
+ optionally directory name. filename and linenum may not be NULL.
+ dirname may be NULL, meaning that the caller does not want
+ directory name info, in which case dirname_available must also be
+ NULL. If dirname is non-null, directory info is written to it, if
+ it is available; if not available, '\0' is written to the first
+ byte. In either case *dirname_available is set to indicate whether
+ or not directory information was available.
+
+ Returned value indicates whether any filename/line info could be
+ found. */
extern Bool VG_(get_filename_linenum)
- ( Addr a, Char* filename, Int n_filename,
- UInt* linenum );
+ ( Addr a,
+ /*OUT*/Char* filename, Int n_filename,
+ /*OUT*/Char* dirname, Int n_dirname,
+ /*OUT*/Bool* dirname_available,
+ /*OUT*/UInt* linenum );
/* Succeeds only if we find from debug info that 'a' is the address of the
first instruction in a function -- as opposed to VG_(get_fnname) which