How do I find the file something was defined in using gdb? - debugging

When I type list mystruct into gdb, I receive the lines of code used to define mystruct. How can I ask gdb to give me the file it is reading from to print those lines? Getting that file from the gdb python interface would be preferable. The more easily parsable the better.
Thanks!

For showing definition of a type there is a command ptype:
$ ptype mystruct
...
To know where type is defined, command info types regex:
$ info types ^mystruct$
<filename>:<line>
And to print lines of source file, command list filename:start_line,filename:end_line:
$ list myfile.c:100,myfile.c:110
if not enough
$ list +
Note that there is possible several same type definitions, so info types can give several locations.
Update
Since this is a matter of compatibility between compiler (that generates debugging information, e.g. DWARF) and gdb that reads it, for some reason, it's not always possible to retrieve detailed information, e.g. line number. This can be workaround-ed by using specific tools, e.g. for DWARF there is a dwarfdump tool, that has access to all DWARF information in the file. The output for structure type
struct mystruct {
int i;
struct sample *less;
}
looks like:
$ dwarfdump -ie ./a.out
...
< 1><0x00000079> structure_type
name "mystruct"
byte_size 0x0000000c
decl_file 0x00000002 ../sample.h
decl_line 0x00000003
sibling <0x000000a8>
< 2><0x00000085> member
name "i"
decl_file 0x00000002 ../sample.h
decl_line 0x00000004
type <0x0000004f>
data_member_location 0
< 2><0x0000008f> member
name "less"
decl_file 0x00000002 ../sample.h
decl_line 0x00000005
type <0x000000a8>
data_member_location 4
Here you have information on which line not only type declaration starts, but also line number for each member.
The output format is not very convenient, and heavy - you should write your own parser. But it could be better to write your own tool using libdwarf or utilize pyelftools on python. Here is one of examples.

In case you have compiled with debug information (-g3) option,
you can use:
info macro mystruct
e.g
info macro SOCK_RAW
(gdb) info macro SOCK_RAW
Defined at /usr/include/x86_64-linux-gnu/bits/socket_type.h:33
included at /usr/include/x86_64-linux-gnu/bits/socket.h:38
included at /usr/include/x86_64-linux-gnu/sys/socket.h:38
included at /home/nirl/cpp_tut/filter/filter.cpp:1
``

Related

How to implement file-substitution macro in bash?

I have a set of text files and a set of GoLang files. The GoLang files contain directives such as the following:
//go:embed hello.txt
var s string
I want to write a bash script which takes the above code and substitutes the following in its place:
var s string = "<contents of hello.txt>"
Specifically, I want to bash script to go through all GoLang source files and replace all go:embed/string declaration pairs with a string defined to be the contents of the file specified in the embed directive.
I'm wondering if there is an existing program which can be configured to do the above. Otherwise, I'm planning on writing the algorithm myself.
Further explaination:
I am trying to replicate GoLang's embed directive (https://tip.golang.org/pkg/embed/).
We are not yet on GoLang 1.16, so we cannot use this functionality, but we are replicating it as closely as possible so that moving over to the standard implementation is as painless as possible.
Below is an attempt at solving your problem:
for i in file1 file2; do
awk '/^\/\/go:embed /{f=$2;next}/^var/&&f{printf"%s = \"",$0;system("cat "f);print"\"";f=0;next}1' < "$i" > "$i.new"
done
The awk script prints all normal lines, only if it encounters the embed directive this line will be skipped (and the file name remembered in variable f). A subsequent line starting with var will then be extended by the content of the file with the remembered name (using the system call "cat").
Beware, there are no error checks at all, no attempt to fix quotes and whatever. So for practical use - unless the file contents you are about to embed are known to be good-natured - you probably have to take a more sophisticated approach.

Ghostscript -d vs -s command line parameters

I recently upgraded Ghostscript from 9.10 to 9.53.3 (also tried 9.50 first). Scripts that have run for years started failing with
Unrecoverable error: rangecheck in .putdeviceprops
After some research and trial and error testing, it seems that Ghostscript changed some of the command line switches from "-s" to "-d". for example:
-sGrayImageResolution=600 now errors but -dGrayImageResolution=600 does not.
Some switches appear to accept either form. For example:
-sColorImageResolution=600 and -dColorImageResolution=600 both work.
(Note: When I say "work" I mean they do not throw the error.)
I have 2 questions
Where can I find a complete list of Ghostscript command line parameters? The Ghostscript documents seem to be incomplete.
What is the difference between -s and -d for a switch? (this is really just a curiosity question)
Thanks
The ColorImageResolution and GrayImageResolution are PostScript distiller parameters found in the VectorDevices.htm#PDFWRITE so are used with setdistillerparams and currentdistillerparams in the PostScript code for -sDEVICE=pdfwrite. Also see TN 5151 Acrobat Distiller Parameters. For example:
<< /MonoImageResolution 72 >> setdistillerparams
EDIT: Here are some more: distillerparams
Some settings can be defined in the system dictionary without error except are never used for anything. Be sure to check all of the documentation. There are some settings not listed in the documentation that can be found by searching in the ghostscript Resource/Init files especially for advanced users. Some of these are unique to ghostscript and beyond normal PostScript.
This is from the ghostscript Use.htm#Options :
-Dname
-dname
Define a name in systemdict with value=true.
-Dname=token
-dname=token
Define a name in systemdict with the given value. The value must be a valid PostScript token (as defined by the token operator). If the
token is a non-literal name, it must be true, false, or null. It is
recommeded that this is used only for simple values -- use -c (above)
for complex values such as procedures, arrays or dictionaries.
Note that these values are defined before other names in systemdict, so any name that conflicts with one usually in systemdict
will be replaced by the normal definition during the interpreter
initialization.
-Sname=string
-sname=string
Define a name in systemdict with a given string as value. This is different from -d. For example, -dXYZ=35 on the command line is
equivalent to the program fragment
/XYZ 35 def
whereas -sXYZ=35 is equivalent to
/XYZ (35) def

What is the meaning of ATS_PACKNAME?

For instance, I saw the following line in ATSLIB:
#define ATS_PACKNAME "ATSLIB.libats.deqarray"
What is the meaning of this line? What purpose does it serve?
Say you declare a function in a file XYZ.dats:
extern fun foo (...): ...
The ATS compiler generates a global name for foo using the full path
of XYZ.dats, which is often hard to read.
If the flag ATS_PACKNAME is set, then the global name for foo is
${ATS_PACKNAME}foo, where ${ATS_PACKNAME} is the string value of
ATS_PACKNAME.
http://discourse.ats-lang.org/t/ats-packname/645/2

How to grep on gdb print

Is there a way to grep on the output of print command in gdb? In my case, I am debugging a core dump using gdb and the object I am debugging contains hell lots of elements. I am finding it difficult to look for a matching attribute i.e:
(gdb) print *this | grep <attribute>
Thanks.
You can use pipe command
>>> pipe maintenance info sections | grep .text
[15] 0x5555555551c0->0x5555555554d5 at 0x000011c0: .text ...
>>> pipe maintenance info sections | grep .text | wc
1 10 100
(gdb) print *this | grep
The "standard" way to achieve this is to use Meta-X gdb in emacs.
An alternative:
(gdb) set logging on
(gdb) print *this
(gdb) set logging off
(gdb) shell grep attribute gdb.txt
The patch mentioned by cnicutar sure looks attractive compared to the above. I am guessing the reason it (or its equivalent) was never submitted is that most GDB maintainers use emacs, and so don't have this problem in the first place.
The simplest way is to exploit gdb python. One-liner:
gdb λ py ["attribute" in line and print(line) for line in gdb.execute("p *this", to_string=True).splitlines()]
Assuming you have enabled history of commands, you can type this just once, and later then press Ctrl+R b.exec to pull it out of history. Next simply change attribute and *this per your requirements.
You can also make this as simple as this:
gdb λ grep_cmd "p *this" attribute
For that just add the following to your .gdbinit file:
py
class GrepCmd (gdb.Command):
"""Execute command, but only show lines matching the pattern
Usage: grep_cmd <cmd> <pattern> """
def __init__ (_):
super ().__init__ ("grep_cmd", gdb.COMMAND_STATUS)
def invoke (_, args_raw, __):
args = gdb.string_to_argv(args_raw)
if len(args) != 2:
print("Wrong parameters number. Usage: grep_cmd <cmd> <pattern>")
else:
for line in gdb.execute(args[0], to_string=True).splitlines():
if args[1] in line:
print(line)
GrepCmd() # required to get it registered
end
I know this is an old post but since I found it looking to do the same thing I thought I would add to Hi-Angel's answer to say you can highlight the search term, in the python output, in a red colour by replacing the print line with the one below:
print(line.replace(args[1], "\033[91m"+args[1]+"\033[0m"))
This just uses ascii escape commands for the colour, so should work on Linux and Windows terminal, and you can easily change the colour.
Sorry, don't have enough rep to add this as a comment.

In GDB how do I resolve duplicate symbols

I have a global variable that's name has multiple symbols and I want to print all of them. Example:
(gdb) info var g_reallocCount
All variables matching regular expression "g_reallocCount":
File sv.c:
long int g_reallocCount;
long int g_reallocCount;
long int g_reallocCount;
long int g_reallocCount;
when I try to use "print g_reallocCount" i get only one result, and it is not the one that I need.
I believe that the reason I have multiple symbols is that the static library I am changing is linked to multiple loaded modules. At this time I am not sure whether I can change that fact.
thanks
Edit: for some reason I failed to consider an easier way initally... assuming c linkage.
(gdb) shell nm /path/to/stuff | grep g_reallocCount | cut -d' ' -f1 >>foo
(gdb) shell cat foo | awk '{print "p *0x" $0}' >foo.gdb
(gdb) source foo.gdb
$4 = 0
$5 = 0
$6 = 0
original answer, similar premise:
For lack of a better idea, you can try copying the binary/library and stripping it of debug symbols with the strip command, gdb will then output the address of the symbol in 'info var'
and you can print it with print *0xaddr
I'll come up with a patch to print the address of the variable in 'info var', when debug symbols are available.
If you come up with a minimal testcase to reproduce this, please consider sending it to the gdb lists, or attaching it to a bug report.
Thanks!

Resources