Is it possible to declare a GDB convenience variable as an array? - gdb

I would like to declare an array convenience variable, such as
set $list[10]
but I get a syntax error.
Is it possible to create a vector using convenience variables?
I could use pointers, if I can find an absolute area memory GDB can use that the target program won't use.
Oh, BTW, I don't have a symbol table for the target program I am debugging, using a compiler not compatible with GDB.
The cross-target version of GDB I have does not support python.

I think it is only possible if you allocate memory in the inferior. That is, try something like:
set $list = (int *) malloc (10 * sizeof (int))
Change the types to suit.
Another similar option is to use the {...} feature. I am not sure offhand, but I think this may allocate memory in the inferior in some cases. Anyway, try:
print {1,2,3,4}[2]
I get
$1 = 3

Yes, you can.
For example,
(gdb) set $a = (int [3]) {0}
(gdb) p $a
$14 = {0, 0, 0}

Related

Debugging with gdb - (gdb) "x/s pointer" output

I am trying to debug using gdb. I got that if you want output in string you have to use "x/s Ptr". It works fine some time. But many times I am getting either Null value i.e. " " or some random numeric values. My file has 10000 lines of codes. :-p Please find some gdb output. For e.g.
krb5_get_credentials_for_user (context=0x59c00eb0, options=4, ccache=0x5a001d40, in_creds=0x5ab022a8, subject_cert=0x0,
out_creds=0x5ab02378) at test_abc.c:696
(gdb) x/s 0x59c00eb0
0x59c00eb0: "$\247\016\227"
(gdb) x/s 0x5ab022a8
0x5ab022a8: ""
Could someone please tell me how I can solve this prob? Thanks in advance!
But many times I am getting either Null value i.e. " " or some random numeric values.
There is nothing wrong with what you show. It's just that the memory location you are examining isn't pointing to a string (0x59c00eb0) or is pointing to an empty string (0x5ab022a8).
You didn't present any evidence that these locations should be pointing to a string, and in fact, as (now deleted) comment showed context points to struct _krb5_context, which contains magic number as the first member. Therefore, you should use x/w to examine it.
... fine some times. But many times I am getting either Null value i.e. " "
or some random numeric...
Been there, done that. Allow me to encourage you to be creative.
I sometimes create a function (call it foo? bar? show? dump?), that is not used by the program being debugged. The function is often c-style (because gdb seems to understand that better, and simpler to invoke), global scope, simple. The temporary install of this function close (in the same file?) to what you want to improve the visibility of sometimes helps.
I can then invoke this function using the gdb p command, such as
gdb> p foo
it is possible to pass parameters to foo, but if I'm touching the code to debug something, I usually make foo more capable ... when no parameters it does one thing. Or perhaps use an int parameter (bar(7)) that switches to show more or differently.
Experiment.
This is not typical, and I suspect better knowledge of gdb might be worth the effort, if I could remember it to the next time I need it. Sometimes gdb just doesn't understand, and I can't figure out why. Other times, I get away with adding a pointer and trying to print that:
gdb> p *foobar

Why Is This Pointer Being Copied Incorrectly? Why Does The Segmentation Fault Not Occur Earlier?

I am debugging a program that reads data from a binary file and puts it into the fields of a TaggerDataUnigram object, TaggerDataUnigram being a class derived from TaggerData. All the reading operations read a number of data objects specified in the file and put the objects into fields of TaggerData. Therefore, I defined a function ReadForNumberToRead that takes a file and a Reader* as arguments, Reader being a base class for functors that define how to read the data from the file. Each Reader derivative takes a TaggerData* as an argument and stores the value of the pointer as a member. Unfortunately, TaggerData uses getters and setters, but the getters return references to the fields. So, for example, OpenClassReader accesses TaggerData::open_class through tagger_data_pointer_->getOpenClass().
Example: ForbiddingRuleReader's Constructor:
ForbiddingRuleReader::ForbiddingRuleReader(
FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
tagger_data_pointer_ is a protected member of Reader.
Reader::Reader(FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: TaggerDataFileInputOutput(tagger_data_input_file_reference),
tagger_data_pointer_(tagger_data_pointer) {} // tagger_data_pointer_ is initialized.
. . . and the identical constructor of ArrayTagReader:
ArrayTagReader::ArrayTagReader(FILE*& tagger_data_input_file_reference,
TaggerData* tagger_data_pointer)
: Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
Their usages are likewise the same:
void TaggerDataUnigram::ReadTheForbiddingRules(
FILE*& unigram_tagger_data_input_file_reference) {
ForbiddingRuleReader forbidding_rule_reader(
unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&forbidding_rule_reader);
}
[. . .]
void TaggerDataUnigram::ReadTheArrayTags(
FILE*& unigram_tagger_data_input_file_reference) {
ArrayTagReader array_tag_reader(unigram_tagger_data_input_file_reference,
this);
ReadForNumberToRead(unigram_tagger_data_input_file_reference,
&array_tag_reader);
}
Needless to say, the TaggerDataUnigram object is not going out of scope.
OpenClassReader and ForbiddingRuleReader both work perfectly; they store a copy of the file and TaggerData* as fields and successively read data from the file and put it into its respective field in TaggerData. The problem arises when the ArrayTagReader is constructed. Despite sharing an identical constructor and being used the same way as ForbiddingRuleReader, something goes terribly wrong--tagger_data_pointer_ does not point to the same location in memory as the TaggerData* tagger_data_pointer the object was constructed with!
Breakpoint 1, ArrayTagReader::ArrayTagReader (this=0x7fffffffd640, tagger_data_input_file_reference=#0x7fffffffd720: 0x62a730, tagger_data_pointer=0x7fffffffd8c0)
at array_tag_reader.cc:10
10 : Reader(tagger_data_input_file_reference, tagger_data_pointer) {}
(gdb) print tagger_data_pointer
$1 = (TaggerData *) 0x7fffffffd8c0 <----------
(gdb) continue
Continuing.
Breakpoint 2, ArrayTagReader::operator() (this=0x7fffffffd640) at array_tag_reader.cc:12
12 void ArrayTagReader::operator()() {
(gdb) print tagger_data_pointer_
$2 = (TaggerData *) 0x7fffffffd720 <----------
In both OpenClassReader and ForbiddingRuleReader, tagger_data_pointer_ is equal to tagger_data_pointer.
Strangely, errors do not result immediately, even though the pointer is clearly invalid.
Breakpoint 3, ArrayTagReader::operator() (this=0x7fffffffd640) at array_tag_reader.cc:12
12 void ArrayTagReader::operator()() {
(gdb) print *tagger_data_pointer_
$3 = {_vptr.TaggerData = 0x62a730, open_class = std::set with 0 elements, forbid_rules = std::vector of length 275736, capacity -17591907707330 = {{tagi = -1972060027,
[. . .]
However, upon the first call of TagIndexReader::operator(), the program encounters a segmentation fault, specifically SIGSEGV. It's no surprise; though TagIndexReader's tagger_data_pointer_ is valid, a great part of the TaggerDataUnigram object was compromised.
Breakpoint 4, TagIndexReader::operator() (this=0x7fffffffd650) at tag_index_reader.cc:7
7 void TagIndexReader::operator()() {
(gdb) print tagger_data_pointer_
$16 = (TaggerData *) 0x7fffffffd8c0 <---------- This is the correct value.
(gdb) print *tagger_data_pointer_
$17 = {_vptr.TaggerData = 0x41e5b0 <vtable for TaggerDataUnigram+16>,
open_class = std::set with 6467592 elements<error reading variable: Cannot access memory at address 0x5200000051>,
Why is tagger_data_pointer being copied incorrectly? Why does the program not encounter a segmentation fault immediately after trying to write to invalid memory? How can I resolve this issue?
Thank you for your time.
Update:
These might be useful:
void ArrayTagReader::operator()() {
std::wstring array_tag = Compression::wstring_read(
tagger_data_file_reference_);
tagger_data_pointer_->getArrayTags().push_back(array_tag);
}
void ReadForNumberToRead(
FILE* tagger_data_input_file_reference,
Reader* pointer_to_a_reader) {
for (int unsigned number_to_read =
Compression::multibyte_read(tagger_data_input_file_reference);
number_to_read != 0;
--number_to_read) {
pointer_to_a_reader->operator()();
}
}
Update:
Somehow, I missed the declaration of tagger_data_poiner_ in ArrayTagReader; making the pointers const generated the compiler error that brought this to my attention. What I still don't understand is why:
The compiler didn't complain about the use of an uninitialized pointer.
The program did not encounter a segmentation fault when trying to modify e.g. tagger_data_poiner_->getArrayTags().
"tagger_data_pointer_ does not point to the same location in memory as the TaggerData* tagger_data_pointer the object was constructed with"
That generally means the value has been overwritten. A very common cause is an buffer overflow in the preceding field, or less common an _under_flow in the following field. It also explains why this is a problem that occurs only n one of your two classes; the other class has other neighbors. Still, not all overwrites are buffer over/underflows. Invalid typecasting is another possible problem.
Since you don't mean to change the pointer, do make it const. A second debugging technique is to replace the field with an array of 3 identical copies. Create a function that checks if all three are the same, throws if not, and otherwise return the single value. In the places where you dereferenced the pointer, you now call this check function. This gives you a good chance to detect the exact nature of the change. Even more fancy algorithms add extra padding data with known values.
Despite sharing an identical constructor and being used the same way as ForbiddingRuleReader
I'm not sure why you think these are important, but I can tell you that according to the C++ standard, these have absolutely no relevance concerning whether two types have the same memory layout or whether one can reinterpret_cast (or the moral equivalent) between them.
I was not able to read your code properly as everything but the "UPDATE" is extremely messy and very hard to read for anyone but the author. The UPDATE part seems OK. So I'll just drop by a few tips on copying using pointers (as I recently saw that many people make these mistakes) and maybe it helps.
Make sure you're not just copying from or to a memory location that is not "marked" as allocated. In other words, if you have a pointer and you're just copying data in array to memory location it points to, nothing stops your program or other programs currently running on the computer to modify that area. You first allocate space (using new, malloc etc.) and then you can copy from/to it.
type *p = new type[size];
Even if you've satisfied point 1, make sure copied space doesn't exceed size.
Advice on the question, by comments on it (I can't comment ATM)...
You may be a really good programmer. But you'll make mistakes. Meaning you'll have to find them. Meaning you should keep your code tidy. But there's far more crucial reason for being tidy. People reading your code don't really know where everything "should" be. For them reading a messy code is mission impossible. That's important because someone might have to continue your work for the company on your code. Or if you're looking for help from other programmers, like you're doing right now, you need people to get you.
An indentation should be 1 tab or 4 spaces (you can't use tab on StackOverflow), for every sub-block in your code (covered with { }), unless if the block is empty.
If an instruction is continuing in the next row because of the length, it also deserves an indent. In this case you can also add additional tabs or spaces to make everything look nice. For example, if you have an equation long enough to be separated in 3 rows, you can make every row start from '=' of the first row.
"UPDATE" section looks much better than the rest, but you should still use 4-space indent instead of 2-space indent.

LLDB C++ debugging

I am new to LLDB and I am working with various std::vectors in my code, however when I try to print the values of a vector or to query the size of my vector with something like expr '(int)myVector[0]' or expr '(int)myVector.size()' the debugger prints values that have nothing to do with the values I know there are in the vector.
As I'm learning to debug with command line and LLDB, I'm sure I'm missing something here, can anyone spot my error or give some advise?
EDIT Forgot to say that I'm under OS X Mavericks with the latest command-line tools installed.
I found the answer myself. Apparently the overloaded operators like [] are not allowed since they are inlined, see this question for a better explanation on that.
Moreover, I don't know why did I put single quotes for the statement I wanted to evaluate (I'm pretty sure I saw it in other place ... what do they actually mean in LLDB?) like so expr 'printf("Hey")'
So, taking out the quotes and using the answer in the cited question it suffices with something like
expr (int) myVector.__begin_[0]
to get the single value of a position in the vector.
Use p myVector or po myVector. These will print out the contents of your vector (alongside the size) in a couple of different formats.
To print a single value from the vector, you can use something like p (int)myVector[0].

Display a pointer value with lldb debugger

I'm working in a personal project of open-source technologies developing an application build it in C. I'm using the lldb debugger tool.
My question is simple: How can I display or show the values of an element when I'm debugging.
For example:
#include <iostream.h>
int main(){
char phrase[1024];
int i=0;
for(i=0;i<1024;i++){
printf("%c",phrase[i]);
}
return 0;
}
In the lldb prompt, I can see the values for specific character of the array:
lldb>b 6
lldb>frame variable phrase[0];
When I want to execute:
lldb>frame variable phrase[i]
I got an error: "unable to find any variable expression path that matches 'phrase[i]'"
You need to use
(lldb) expr phrase[i]
or equivalently
(lldb) p phrase[i]
for that
frame variable supports constant indexes (i.e. plain ol’ numbers), but if you need to use a variable or anything BUT a number, you need to use the expression command
As a caveat, the behavior of frame var vs. expression might be different in some cases when doing array-like access. This won’t affect your example (but it would if you were using an std::vector, for instance).

Create variable with list of strings

I would like to know if it's possible to use the content of a variable list of strings to create a new variable.
As an example:
str={"cow","monkey"}
these strings are extracted from a file. Now I would like to refer to these strings as if it was a variable. So the variable cow could be set to {4,2,3} or anything else. Any reference as str[[1]] gives the string "cow" of course.
Any clues or is this a bad idea anyway?
Of course I could add info in the list I already have such as:
str={{"cow",{4,2,3}},{"monkey",{}}
but then I still won't be able to directly address cow as a variable.
The simplest would be to just manually use symbols cow and monkey rather than strings:
In[309]:=
cow = 1;
monkey = 2;
{cow, monkey}
Out[311]= {1, 2}
But this is probably not what you asked. If you want to automatically convert strings to variables, then
what you have to do (if I understood the question correctly) is to first convert your strings to symbols, since symbols can be assigned values and used as variables:
Remove[cow,monkey];
str = {"cow", "monkey"};
str1 = ToExpression /# str
{cow, monkey}
(I assume that symbols cow and monkey have not been used/defined). After that, you can use the answer for this question to assign to the variables based on their positions in str1. However, the usefulness of this approach is also questionable.
What I think makes the most sense is to create so called indexed variables, such as
myIndexedVar["cow"] = 1;
myIndexedVar["monkey"] = 2;
where myIndexedVar is essentially a hash-table of key-value pairs, with keys being your strings and values being whatever you want to assign to them. The process can be automated if needed.
EDIT
To illustrate assignments to such variables, here is a function which automates that:
assignVariables[varNames_List, values_List, hashName_Symbol ] /;
Length[varNames] == Length[values] :=
MapThread[(hashName[#1] = #2) &, {varNames, values}];
Here is how you can use it:
In[316]:= assignVariables[str,{{4,2,3},{}},myIndexedVar]
Out[316]= {{4,2,3},{}}
In[317]:= myIndexedVar["cow"]
Out[317]= {4,2,3}
In[318]:= myIndexedVar["monkey"]
Out[318]= {}
But again, this really is a hash-table, so your question makes most sense to me when reformulated as: "I want to make a hash-table with string keys. What's the easiest way to do that in Mathematica, add key-value pairs and access them". The answer seems to be - indexed variables, as illustrated above. You may also find it useful to read on DownValues, since these provide the mechanism for indexed variables.
Leonid's last method is probably the best, but I am fond of replacement rules, therefore I offer:
str={"cow","monkey"};
rules = {"cow" -> {4,2,3}, "monkey" -> {}};
str[[1]] /. rules
Out = {4, 2, 3}
See Rule, and ReplaceAll for more.
ToExpression will convert a string to an expression. Symbol["x"] creates the symbol x as the name suggests.
However, I wonder how you plan to use them. If you don't know a priori what's in the file with names how are you going to use them? If str={"cow","monkey"} and I create a list of symbols with strSym=ToExpression/#str then the only way I could continue in my code is to index this second array. I cannot simply say cow=5 in my code because I don't know at the time of writing the code that there will be a variable named cow.
In[1]:= str = {"cow", "monkey"};
strSym = ToExpression /# str
Out[2]= {cow, monkey}
In[3]:= strSym[[1]] // Evaluate = 5
Out[3]= 5
In[4]:= ?cow
Global`cow
cow=5
As you can see, indexing also requires an additional Evaluate, because Set (=) has HoldFirst as Attribute. So I can't set cow by indexing unless I have the index evaluated otherwise I overwrite the definition of strSym[[1]] .