LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   static local vars doubt..... (https://www.linuxquestions.org/questions/programming-9/static-local-vars-doubt-4175460860/)

webquinty 05-06-2013 03:38 AM

static local vars doubt.....
 
Hello,

I have two functions and both has a static local var....

Code:

void comm_tk_init(void)
{
static UINT prueba;

        prueba = 1;
}


void comm_tk_cyclic(void)
{
static UINT prueba;

        prueba = 0;
}

Now, I check address of each var..

Code:

john@linux-2sn9:~/workspace/Applications/QT_template> nm -f sysv QT_template
prueba.3188        |08068748|  d  |            OBJECT|00000002| 
prueba.3192        |0806874a|  d  |            OBJECT|00000002|

Code:

< 1><0x000000a4>    DW_TAG_subprogram
                      DW_AT_external              yes(1)
                      DW_AT_name                  comm_tk_init
                      DW_AT_decl_file            0x00000001 TaskClass1/comm_tk.c
                      DW_AT_decl_line            0x00000013
                      DW_AT_prototyped            yes(1)
                      DW_AT_low_pc                0x0804d998
                      DW_AT_high_pc              0x0804d9ad
                      DW_AT_frame_base            <loclist with 3 entries follows>
                        [ 0]<lowpc=0x00000000><highpc=0x00000001>DW_OP_breg4+4
                        [ 1]<lowpc=0x00000001><highpc=0x00000003>DW_OP_breg4+8
                        [ 2]<lowpc=0x00000003><highpc=0x00000015>DW_OP_breg5+8
                      DW_AT_sibling              <0x000000cf>
< 2><0x000000bd>      DW_TAG_variable
                        DW_AT_name                  prueba
                        DW_AT_decl_file            0x00000001 TaskClass1/comm_tk.c
                        DW_AT_decl_line            0x00000014
                        DW_AT_type                  <0x00000065>
                        DW_AT_location              DW_OP_addr 0x08068748
< 1><0x000000cf>    DW_TAG_subprogram
                      DW_AT_external              yes(1)
                      DW_AT_name                  comm_tk_cyclic
                      DW_AT_decl_file            0x00000001 TaskClass1/comm_tk.c
                      DW_AT_decl_line            0x00000020
                      DW_AT_prototyped            yes(1)
                      DW_AT_low_pc                0x0804d9ad
                      DW_AT_high_pc              0x0804d9bb
                      DW_AT_frame_base            <loclist with 3 entries follows>
                        [ 0]<lowpc=0x00000015><highpc=0x00000016>DW_OP_breg4+4
                        [ 1]<lowpc=0x00000016><highpc=0x00000018>DW_OP_breg4+8
                        [ 2]<lowpc=0x00000018><highpc=0x00000023>DW_OP_breg5+8
                      DW_AT_sibling              <0x000000fa>
< 2><0x000000e8>      DW_TAG_variable
                        DW_AT_name                  prueba
                        DW_AT_decl_file            0x00000001 TaskClass1/comm_tk.c
                        DW_AT_decl_line            0x00000021
                        DW_AT_type                  <0x00000065>
                        DW_AT_location              DW_OP_addr 0x0806874a

Now, How can I know that Variable belongs to its function?
I suppose that gcc add that number but what is the criteria?

Best regards.

pan64 05-06-2013 03:58 AM

I do not think there is an "official" way for it, because those vars are local and access is not allowed from outside. So you need to find the function itself, disassemble and you will find the address of the given local variable

mina86 05-06-2013 04:01 AM

Quote:

Originally Posted by webquinty (Post 4945790)
Now, How can I know that Variable belongs to its function?

Strictly speaking, static “local” variables do not belong to anyone, but since they are defined inside a function, their scope is function's body, which means that they can be accessed (by name) only inside the function.

Short answer to your question is: you cannot. Why would you even need that? What is a problem you are trying to solve?

webquinty 05-06-2013 04:23 AM

Hello,
Thank you for fast answers.

Well, I have developed a function that if I give it a name of var, it return me address, type and length of var using GDB/MI. With global variables, it works fine.
Now, I am interesting in use the same function with local vars, but with static local variables I cannot give the name because gdb return me error "No symbol "prueba" in current context" and it is normal.

But if you use other nomenclature...
Quote:

(gdb) p &comm_tk_init::prueba
$3 = (UINT *) 0x8068748 <prueba.3188>
GDB return me correct information.

I'm looking for a relationship between the function and the name of the variable, but understand that your response will be somewhat difficult.

pan64 05-06-2013 04:26 AM

no, it is not difficult at all. I think there is no logical relationship, so those numbers (pointers) are more or less random-like ones.

webquinty 05-06-2013 04:42 AM

So, in few words....

prueba.3188 --> comm_tk_init::prueba
prueba.3192 --> comm_tk_cyclic::prueba

any advice.

pan64 05-06-2013 04:58 AM

Why do you need that? Probably the variables counted and that is the result or that is something like "distance" in bytes from somewhere....

johnsfine 05-06-2013 07:57 AM

First you should understand there are two different kinds of information that gcc puts in the object code for those symbols.

It puts in information needed by the linker to build the correct binary. That is the information you have looked at. In that kind of information, the size of each of those symbols is indicated, but the scope is not (the linker decides on the address). As others indicated, the info for the function indicates how to find the variable, but the info for the variable has no need to point back to the scope.

There is also optional debugging info, that is transformed by the linker into the information used by gdb. The kind of information you want is in that debugging info. I don't recall what commands you use to get readable information from the debugging info in an object file.

sundialsvcs 05-06-2013 08:58 AM

Exactly.

local is a scope, or if you will visibility modifier. The variable-name is visible only to the local context in which it is defined. A static variable that is local will also be a unique instance ... if two separate subroutines define a local variable named x, it will be a distinct variable whether-or-not it is static.

static causes a single unique memory address to be assigned to that variable, and for the lifetime of that address to be the lifetime of the program.

A function is free to divulge the address of one of its local static variables if it wishes to do so, thereby giving anyone else access to it by means of a pointer or indirect reference.

The runtime debugger acts on memory-address based information, and, in the particular situation that you are describing, it can indeed be confusing although it is correct.

webquinty 05-06-2013 09:23 AM

Hi,

well, I understood all post.

local is a scope and if I declare a variable as static in two different functions with the same name, both variables are different and it has own address memory.

But my questions is:
Can I looking for debug information of this vars????
How can I detect that Variable belongs to its function????

prueba.3188 --> variable prueba in comm_tk_init function.
prueba.3192 --> variable prueba in comm_tk_cyclic function.

is it possible to obtain this information with any debug tool like gdb for example?
Note: I dont know the struct of program.

with "nm" tool.....
Quote:

prueba.3188 |08068748| d | OBJECT|00000002|
prueba.3192 |0806874a| d | OBJECT|00000002|
second step: how to know that Variable belongs to its function????

Best regards.

pan64 05-07-2013 12:22 AM

No, you still not understand. Scope works on the language level, I mean you will use it inside the c/c++ code to define accessibility. The compiler checks it and will throw and error in case of a violation (syntax rules). That is the first task what a compiler must do.
The following phases will translate to code to binary, will collect all the variables (probably some optimization will happen) and will construct a result file (lib, app, whatever). Here you do not need/have scope at all, and also using direct memory access you can reach whatever you want. In this level you have only pointers to different parts of the memory...

mina86 05-07-2013 07:53 AM

Quote:

Originally Posted by pan64 (Post 4946327)
In this level you have only pointers to different parts of the memory...

However, with debug symbols it should be able to get from the pointer back to the variable, and I'm guessing that's what OP is asking about.

johnsfine 05-07-2013 08:30 AM

I'm far from expert in this stuff, but I tried creating a .c file similar to what the OP described, then compiling (gcc -g -c ...) to create a .o file with debug info. Then I used readelf -w to dump out the debug info from the .o file.

It is very verbose, with lots of content (such as from the include files) that I don't really understand.

But searching for the repeated variable name, it was easy to find a (DW_TAG_variable) section in the output for each of them. Then searching backward in the output from that DW_TAG_variable section, I could find the next earlier (DW_TAG_subprogram) section, which appears to give the scope of the variable. So I can infer the basic rules.

I also put another static variable of the same name at module scope (outside of any subprogram) and was surprised to see its DW_TAG_variable at the end of the output with nothing that I understand telling me it is not part of the next earlier DW_TAG_subprogram.

So there is more complexity than I can deduce with a quick test. Maybe there is enough complexity that studying the source code of readelf would be required.

But close to what the OP wants can be achieved by parsing the output of readelf. It would be better (though I'm not sure whether harder or easier) to do the same by calling the same functions that readelf calls. That is part of the beauty of open source.

Edit: I wasn't looking at the obvious. Each section of that output starts with a level number in <>. So the variables in subprogram scope each start with <2> so you know to look backward for the next earlier <1> to get their scope. The static variable at module scope has its section start with <1> so you know there is no outer scope. The file is also identified. There is a DW_AT_external entry in the global sections to distinguish a <1> meaning global from a <1> meaning file scope.

Edit2: After figuring all that out, I looked again at the output the OP showed in the first post. When I first saw that, I knew neither where the OP got that output, nor what it meant. But I see it is nearly the same as what I got from readelf -w including the key fact (that may be the whole answer to the OP's question) that the level numbers <1> and <2> combined with the sequence in which those sections appears, tells you the way the scopes nest.

webquinty 05-07-2013 09:10 AM

Hello johnsfine,

Thank you.
Yes, you are right. With dwarf, is clear ( more or less ) how to find variables.

I would like to make the same with GDB but it is more complex.

Best regards.

ntubski 05-07-2013 12:42 PM

Maybe gdb's info scope command is what you need:
Code:

% gdb comm_tk
GNU gdb (GDB) 7.4.1-debian
[...snip...]
Reading symbols from /home/npostavs/tmp/comm_tk...done.
(gdb) info functions
All defined functions:

File comm_tk.c:
void comm_tk_cyclic(void);
void comm_tk_init(void);
int main();

Non-debugging symbols:
0x0000000000400370  _init
[...snip...]
(gdb) info scope comm_tk_cyclic
Scope for comm_tk_cyclic:
Symbol prueba is in static storage at address 0x6008f4, length 4.
(gdb) info scope comm_tk_init
Scope for comm_tk_init:
Symbol prueba is in static storage at address 0x6008f8, length 4.



All times are GMT -5. The time now is 12:00 AM.