How do I print floats as exponentials in gdb? - gdb

I want to print my variables in exponential form. Currently, I get:
(gdb) set $x=200.0500
(gdb) print $x
$3 = 200.05000000000001
I want:
2.00E+002
or
2.00E2
In other words, I want to control the digits printed also the exponential form.

I did find an answer myself:
(gdb) python print "%0.2e" % (gdb.parse_and_eval('200.0000'))
2.00e+02

Related

How to use gdb to decode stack trace (show line numbers)

I know I can use info line *<addr> within gdb to decode a single line. But a stack trace has 10+ addresses. Is there an efficient way to let me copy and paste a list of addresses (also without the leading *) and it will list the filenames and line numbers much like the bt command but without the core dump?
Based on the suggestion of #ssbssa, I wrote the following user-defined command that works for me.
define decode
set $i = 0
while $i < $argc
eval "info line *($arg%d)", $i
set $i = $i + 1
end
end

Does gdb support comments in the command line (gdb prompt)?

I want to comment gdb commands in the command prompt at the end of the line for two use case:
Writing a tutorial
Documenting a gdb command file for automatic execution
While gdb command files seem to support comments via the hash (#) symbol
I cannot find any command marker for the gdb command line:
(gdb) print 1
$2 = 1
(gdb) print 1 // comment
A syntax error in expression, near `/ comment'.
(gdb) print 1 -- comment
A syntax error in expression, near `comment'.
(gdb) print 1 # comment
Invalid character '#' in expression.
(gdb) print 1 ; comment
Invalid character ';' in expression.
(gdb) print 1 /* comment */
No symbol "comment" in current context.
How can I append comments?
Edit: According to the gdb documentation
Any text from a # to the end of the line is a comment;
it does nothing.
This is useful mainly in command files
I am not sure why it doesn't work as documented...
You can use it on its own line, but not at the end of a line. E.g.:
(gdb) # foo
(gdb) print "foo"
$1 = "foo"

Can I print the content of the rax register with leading zeros?

When I print the content of the eax register in a gdb session in hexadecimal format, it does not print leading zeros:
(gdb) p/x $rax
$6 = 0x3
I am looking for a possibility to extend the output to print all 16 hexadecimal digits so that the output becomes
$6 = 0x0000000000000003
Is there such a feature?
You can use the printf command to use C printf like format strings to format the output.
You can print long values with %lx. Prepend lx with a size like 16 will format a number right justified in the field of the specified size. If you prepend a 0 to the size it will zero fill for you. This should work:
printf "%016lx", $rax
If you want 0x to appear you can add it yourself with:
printf "0x%016lx", $rax

How to perform transformation of CSV file using regular expressions? [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
I was trying to solve one problem for a while now but without success. In start it looks like a trivial issue but I have stacked with it...
Anyhow, I need to solve following problem. I have very large CSV file with lines in following format:
NUMBER(9);NUMBER(1);NUMBER(9-10);NUMBER(2);NUMBER(1);...;NUMBER(2);NUMBER(1);STRING;DATE(DD.MM.YYYY);NUMBER(1351)
for example:
517755369;1;0001303717;48;1;63;8;50;2;51;6;53;7;55;3;57;4;59;5;;;;;CALL;07.12.2012;1351
In each line after first tree fields I have 1 to 10 pairs NUMBER(2);NUMBER(1), followed by another three fields STRING;DATE(DD.MM.YYYY);NUMBER(1351).
I need to transform that file in file with following structure:
517755369;1;0001303717;48;1;CALL;07.12.2012;1351
517755369;1;0001303717;63;8;CALL;07.12.2012;1351
517755369;1;0001303717;50;2;CALL;07.12.2012;1351
517755369;1;0001303717;51;6;CALL;07.12.2012;1351
517755369;1;0001303717;53;7;CALL;07.12.2012;1351
517755369;1;0001303717;55;3;CALL;07.12.2012;1351
517755369;1;0001303717;57;4;CALL;07.12.2012;1351
517755369;1;0001303717;59;5;CALL;07.12.2012;1351`
So each line from input file should be transformed to as many lines as original line has NUMBER(2);NUMBER(1) pairs.
Here is a sample of input file:
517760344;2;000601301061;31;1;;;;;;;;;;;;;;;;;;;CALL;07.12.2012;1351
518855369;1;000601303717;48;1;63;8;50;2;51;6;53;7;55;3;57;4;59;5;;;;;CALL;07.12.2012;1351
519775067;1;000601300771;4;2;6;3;19;1;;;;;;;;;;;;;;;CALL;07.12.2012;1351
617773407;1;000603252922;13;1;17;2;27;3;;;;;;;;;;;;;;;CALL;07.12.2012;1351
717764779;1;000601304021;31;1;;;;;;;;;;;;;;;;;;;CALL;07.12.2012;1351`
In general I need some regexp that I can use with sed or awk (or some perl script I can run against input file). The original input file has roughly 1–1.5M records. This task should be finished as quickly as possible (up to 5 minutes for transformation).
Thanks
Ideas from #Kenosis, but different interpretation of specs:
use strict;
use warnings;
while (<DATA>) {
chomp;
my #fields = split /;/;
my $f = 3;
while ($fields[$f]) {
print join( ';', #fields[0 .. 2, $f, $f + 1, -3 .. -1]), "\n";
$f += 2;
}
}
__DATA__
517760344;2;000601301061;31;1;;;;;;;;;;;;;;;;;;;CALL;07.12.2012;1351
518855369;1;000601303717;48;1;63;8;50;2;51;6;53;7;55;3;57;4;59;5;;;;;CALL;07.12.2012;1351
519775067;1;000601300771;4;2;6;3;19;1;;;;;;;;;;;;;;;CALL;07.12.2012;1351
617773407;1;000603252922;13;1;17;2;27;3;;;;;;;;;;;;;;;CALL;07.12.2012;1351
717764779;1;000601304021;31;1;;;;;;;;;;;;;;;;;;;CALL;07.12.2012;1351
output:
perl 14528210.pl
517760344;2;000601301061;31;1;CALL;07.12.2012;1351
518855369;1;000601303717;48;1;CALL;07.12.2012;1351
518855369;1;000601303717;63;8;CALL;07.12.2012;1351
518855369;1;000601303717;50;2;CALL;07.12.2012;1351
518855369;1;000601303717;51;6;CALL;07.12.2012;1351
518855369;1;000601303717;53;7;CALL;07.12.2012;1351
518855369;1;000601303717;55;3;CALL;07.12.2012;1351
518855369;1;000601303717;57;4;CALL;07.12.2012;1351
518855369;1;000601303717;59;5;CALL;07.12.2012;1351
519775067;1;000601300771;4;2;CALL;07.12.2012;1351
519775067;1;000601300771;6;3;CALL;07.12.2012;1351
519775067;1;000601300771;19;1;CALL;07.12.2012;1351
617773407;1;000603252922;13;1;CALL;07.12.2012;1351
617773407;1;000603252922;17;2;CALL;07.12.2012;1351
617773407;1;000603252922;27;3;CALL;07.12.2012;1351
717764779;1;000601304021;31;1;CALL;07.12.2012;1351
Perhaps the following will be helpful:
use strict;
use warnings;
while (<>) {
chomp;
print +( join ';', ( split /;/ )[ 0 .. 4, -3 .. -1 ] ) . "\n";
}
Output on your data:
517760344;2;000601301061;31;1;CALL;07.12.2012;1351
518855369;1;000601303717;48;1;CALL;07.12.2012;1351
519775067;1;000601300771;4;2;CALL;07.12.2012;1351
617773407;1;000603252922;13;1;CALL;07.12.2012;1351
717764779;1;000601304021;31;1;CALL;07.12.2012;1351
Usage: perl file.csv >out.csv.
It appears that you want the first five fields and the last three. The above splits on ;, rejoins with ; and then prints the modified record.
Here's a solution in one-liner form, using the Text::CSV module.
perl -MText::CSV -lwe '$c = Text::CSV->new({
sep_char=>';',
eol=>$/
});
while($r = $c->getline(*STDIN)) {
my #a = splice #$r,0,3; # remove 3 first elements
my #c = splice #$r,-3; # remove 3 last elements
#$r = grep $_ ne '', #$r; # remove empty elements
while(#$r) { # while array is not empty
$c->print(*STDOUT, [#a, splice(#$r,0,2),#c]); # print all elements
} }"
Output:
517755369;1;0001303717;48;1;CALL;07.12.2012;1351
517755369;1;0001303717;63;8;CALL;07.12.2012;1351
517755369;1;0001303717;50;2;CALL;07.12.2012;1351
517755369;1;0001303717;51;6;CALL;07.12.2012;1351
517755369;1;0001303717;53;7;CALL;07.12.2012;1351
517755369;1;0001303717;55;3;CALL;07.12.2012;1351
517755369;1;0001303717;57;4;CALL;07.12.2012;1351
517755369;1;0001303717;59;5;CALL;07.12.2012;1351
So basically, like I said in my comment, remove first 3 elements and 3 last elements and store in separate arrays. Remove empty elements. Loop around the remaining elements and print as necessary.
This might work for you (GNU sed):
sed -r 's/^(([^;]*;){3})(([0-9]+;){2})(([0-9]*;)*)(([^;]*;?){3})$/\1\3\7\n\1\5\7/;Ta;P;:a;D' file
s/^(([^;]*;){3})(([0-9]+;){2})(([0-9]*;)*)(([^;]*;?){3})$/\1\3\7\n\1\5\7/ this substitution command constructs two strings. The first is the intended string followed by a newline, the second is the original string less the first pair of numbers. So ^(([^;]*;){3}) represents the first three fields, (([0-9]+;){2}) the first pair of numbers,(([0-9]*;)*) the remaining pairs of numbers and (([^;]*;?){3})$ the last three fields.
Ta if the substitution command fails jump to label a
P print upto the first newline in the pattern space.
:a label a
D delete upto and including the first newline and begin the next cycle. Do not read in another line until the pattern space is empty.
So, in essence, the s/.../.../ and the D commands are used to invoke a loop which prints a constructed string until the substitution command fails which then ends the loop. The remaining string is deleted completely and the next line is begun.

Scripting in gdb

Say, for example, I have a C source file with a method like foo(a) where a is a character.
I want to print the output of foo for every character is there an easier way than going through systematically and entering p foo('a') then p foo('b')?
Ideally I'd really like to script it so it's a bit quicker.
I managed to figure it out, my code was basically:
define foo_test
set $a = 97
set $b = 123
while $a < $b
p (char)foo($a)
set $a = $a + 1
end
end
perl -e 'foreach $i ("a" .. "z") { print "print foo('\''$i'\'')\n"; }' > /tmp/t.$$ &&
gdb --batch -x /tmp/t.$$ ./a.out ; rm -f /tmp/t.$$
You should also look into GDB Python scripting.
It sounds like the first thing you should add is some "Breakpoint command lists",
those will let you run some gdb commands after a breakpoint has hit.
So if you add so your print runs when someone calls the functions foo,
you should be are getting kind of close.