Function invocation location

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • 1.41421@gmail.com

    #1

    Function invocation location

    I was wondering if it would be possible to find out, from within a
    function, the file and line number where that particular function call
    was invoked, bearing in mind that the function can potentially be
    invoked from many different files. I guess that what I am looking for
    is something similar to the __FILE__ and __LINE__ symbols, but one
    level up in the function call stack.

  • Keith Thompson

    #2
    Re: Function invocation location

    1.41421@gmail.c om writes:[color=blue]
    > I was wondering if it would be possible to find out, from within a
    > function, the file and line number where that particular function call
    > was invoked, bearing in mind that the function can potentially be
    > invoked from many different files. I guess that what I am looking for
    > is something similar to the __FILE__ and __LINE__ symbols, but one
    > level up in the function call stack.[/color]

    No, there's no good portable way to do that.

    You could probably do something involving passing extra arguments to
    your functions, but it wouldn't be pretty.

    A source level debugger should be able to show this information
    interactively.

    What are you trying to accomplish?

    --
    Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
    San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
    We must do something. This is something. Therefore, we must do this.

    Comment

    • castillo.bryan@gmail.com

      #3
      Re: Function invocation location

      I use macros to do it



      #include <stdio.h>

      #define perform_action( a) _perform_action ((a),__FILE__,_ _LINE__)
      void _perform_action (int actCd, const char * file, int lineno);


      void _perform_action (int actCd, const char * file, int lineno) {
      printf("Called perform_action from %s:%d\n", file, lineno);
      }


      int main(void) {
      perform_action( 4);
      return 0;
      }

      Comment

      • 1.41421@gmail.com

        #4
        Re: Function invocation location

        Keith Thompson wrote:[color=blue]
        > 1.41421@gmail.c om writes:[color=green]
        > > I was wondering if it would be possible to find out, from within a
        > > function, the file and line number where that particular function call
        > > was invoked, bearing in mind that the function can potentially be
        > > invoked from many different files. I guess that what I am looking for
        > > is something similar to the __FILE__ and __LINE__ symbols, but one
        > > level up in the function call stack.[/color]
        >
        > No, there's no good portable way to do that.
        >
        > You could probably do something involving passing extra arguments to
        > your functions, but it wouldn't be pretty.
        >
        > A source level debugger should be able to show this information
        > interactively.
        >
        > What are you trying to accomplish?[/color]

        Pretty much what I said: To find out who is invoking a certain
        function, and at what point. I am using an embedded environment, and a
        source level debugger does disturb things so that what I am trying to
        see is not there anymore. The only way I could think of to do it is by
        means of the info above, and well-placed printf (the output of which
        goes to a console accessible through a serial port).

        Comment

        • castillo.bryan@gmail.com

          #5
          Re: Function invocation location

          You can also (sometimes) get stack trace information on linux with the
          functions: backtrace and backtrace_symbo ls. I don't remember what
          information you could get from the functions (if it was file, line, or
          function/symbol name), but I think you could get symbol names for
          functions that weren't static.

          Comment

          • Keith Thompson

            #6
            Re: Function invocation location

            castillo.bryan@ gmail.com writes:[color=blue]
            > I use macros to do it[/color]

            You use macros to do what? Please read
            <http://cfaj.freeshell. org/google/>. Google's posting interface is
            badly broken, but it can be used correctly with just a little extra
            effort.
            [color=blue]
            > #include <stdio.h>
            >
            > #define perform_action( a) _perform_action ((a),__FILE__,_ _LINE__)
            > void _perform_action (int actCd, const char * file, int lineno);[/color]

            Avoid identifiers with leading underscores. Many of them are reserved
            for use by the implementation. Rather than memorizing or looking up
            the rules for which ones are reserved in which contexts, it's best to
            just avoid them altogether (unless you're using something defined for
            you by the implementation) .

            If you want to generate an identifier from an existing one, trailing
            underscores are ok.
            [color=blue]
            > void _perform_action (int actCd, const char * file, int lineno) {
            > printf("Called perform_action from %s:%d\n", file, lineno);
            > }
            >
            >
            > int main(void) {
            > perform_action( 4);
            > return 0;
            > }[/color]

            Otherwise, that looks reasonable. It's a lot of extra work, it only
            goes up one level (going up arbitrarily many levels is going to be
            interesting), and it only works for functions for which you
            specifically provide the feature.

            The most likely reason you'd want this information is for debugging.
            In that case, a good source-level debugger should give you that
            information and a lot more as well. If you want the behavior of the
            function to vary depending on where it's called from, that's almost
            certainly a bad idea, better implemented by just passing an extra
            argument to control the behavior.

            As with a lot of low-level stuff like this, the first thing you should
            do is step back and decide what problem you're actually trying to
            solve. It's likely that there's a better and/or more portable
            solution.

            --
            Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
            San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
            We must do something. This is something. Therefore, we must do this.

            Comment

            • Keith Thompson

              #7
              Re: Function invocation location

              1.41421@gmail.c om writes:[color=blue]
              > Keith Thompson wrote:[color=green]
              >> 1.41421@gmail.c om writes:[color=darkred]
              >> > I was wondering if it would be possible to find out, from within a
              >> > function, the file and line number where that particular function call
              >> > was invoked, bearing in mind that the function can potentially be
              >> > invoked from many different files. I guess that what I am looking for
              >> > is something similar to the __FILE__ and __LINE__ symbols, but one
              >> > level up in the function call stack.[/color]
              >>
              >> No, there's no good portable way to do that.
              >>
              >> You could probably do something involving passing extra arguments to
              >> your functions, but it wouldn't be pretty.
              >>
              >> A source level debugger should be able to show this information
              >> interactively.
              >>
              >> What are you trying to accomplish?[/color]
              >
              > Pretty much what I said: To find out who is invoking a certain
              > function, and at what point. I am using an embedded environment, and a
              > source level debugger does disturb things so that what I am trying to
              > see is not there anymore. The only way I could think of to do it is by
              > means of the info above, and well-placed printf (the output of which
              > goes to a console accessible through a serial port).[/color]

              If a source level debugger masks the problem, it's likely that either
              the debugger is broken or you're dealing with undefined behavior. You
              can do what you want by changing your code, but that's also likely to
              disturb things. (It's worth a try, though.)

              If you know how the compiler lays out stack frames, you *might* be
              able to display the return address in, say, hexadecimal, and map that
              back to the point at which the function was called. This is clearly
              *extremely* system-specific, so we can't really go into it here, but
              it might give you what you need.

              --
              Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
              San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
              We must do something. This is something. Therefore, we must do this.

              Comment

              • 1.41421@gmail.com

                #8
                Re: Function invocation location

                castillo.bryan@ gmail.com wrote:[color=blue]
                > I use macros to do it
                >
                >
                >
                > #include <stdio.h>
                >
                > #define perform_action( a) _perform_action ((a),__FILE__,_ _LINE__)
                > void _perform_action (int actCd, const char * file, int lineno);
                >
                >
                > void _perform_action (int actCd, const char * file, int lineno) {
                > printf("Called perform_action from %s:%d\n", file, lineno);
                > }
                >
                >
                > int main(void) {
                > perform_action( 4);
                > return 0;
                > }[/color]

                Would this not stop working if, instead of using the name of the
                function itself, one invokes it via a pointer?

                Comment

                • jacob navia

                  #9
                  Re: Function invocation location

                  Keith Thompson a écrit :
                  [snip]
                  [color=blue]
                  > If a source level debugger masks the problem, it's likely that either
                  > the debugger is broken or you're dealing with undefined behavior.[/color]

                  It is impossible for a debugger to mask itself completely.
                  Having written a debugger for embedded systems I can tell you,
                  the debugger is a BIG mess that comes upon your poor program.

                  Impossible to do otherwise in cramped conditions, no RAM,
                  no MMU, etc.

                  That the program has "undefined behavior" is obvious, if not he
                  would not be trying to debug !!!
                  [color=blue]
                  > You
                  > can do what you want by changing your code, but that's also likely to
                  > disturb things. (It's worth a try, though.)
                  >[/color]

                  I agree with you in this. The printfs do CHANGE things, and even if
                  the impact is smaller than the impact of the debugger, they DO CHANGE
                  the program, as you said.
                  [color=blue]
                  > If you know how the compiler lays out stack frames, you *might* be
                  > able to display the return address in, say, hexadecimal, and map that
                  > back to the point at which the function was called. This is clearly
                  > *extremely* system-specific, so we can't really go into it here, but
                  > it might give you what you need.
                  >[/color]

                  That is the best solution for this problem. Find out how the
                  compiler lays out the stack frame (an assembly listing will do that)
                  and try to send the hexadecimal return address through the serial
                  line.

                  With the help of a link map, you can figure out where you were called from.


                  jacob

                  Comment

                  • 1.41421@gmail.com

                    #10
                    Re: Function invocation location

                    Keith Thompson wrote:[color=blue]
                    > 1.41421@gmail.c om writes:[color=green]
                    > > Keith Thompson wrote:[color=darkred]
                    > >> 1.41421@gmail.c om writes:
                    > >> > I was wondering if it would be possible to find out, from within a
                    > >> > function, the file and line number where that particular function call
                    > >> > was invoked, bearing in mind that the function can potentially be
                    > >> > invoked from many different files. I guess that what I am looking for
                    > >> > is something similar to the __FILE__ and __LINE__ symbols, but one
                    > >> > level up in the function call stack.
                    > >>
                    > >> No, there's no good portable way to do that.
                    > >>
                    > >> You could probably do something involving passing extra arguments to
                    > >> your functions, but it wouldn't be pretty.
                    > >>
                    > >> A source level debugger should be able to show this information
                    > >> interactively.
                    > >>
                    > >> What are you trying to accomplish?[/color]
                    > >
                    > > Pretty much what I said: To find out who is invoking a certain
                    > > function, and at what point. I am using an embedded environment, and a
                    > > source level debugger does disturb things so that what I am trying to
                    > > see is not there anymore. The only way I could think of to do it is by
                    > > means of the info above, and well-placed printf (the output of which
                    > > goes to a console accessible through a serial port).[/color]
                    >
                    > If a source level debugger masks the problem, it's likely that either
                    > the debugger is broken or you're dealing with undefined behavior. You
                    > can do what you want by changing your code, but that's also likely to
                    > disturb things. (It's worth a try, though.)[/color]

                    There are some timing considerations that the debugger interferes
                    with in an unavoidable way. On the other hand, a few printf statements
                    do not disturb such considerations significantly.

                    [color=blue]
                    > If you know how the compiler lays out stack frames, you *might* be
                    > able to display the return address in, say, hexadecimal, and map that
                    > back to the point at which the function was called. This is clearly
                    > *extremely* system-specific, so we can't really go into it here, but
                    > it might give you what you need.
                    >
                    > --
                    > Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                    > San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                    > We must do something. This is something. Therefore, we must do this.[/color]

                    Comment

                    • Keith Thompson

                      #11
                      Re: Function invocation location

                      jacob navia <jacob@jacob.re mcomp.fr> writes:[color=blue]
                      > Keith Thompson a écrit :
                      > [snip]
                      >[color=green]
                      >> If a source level debugger masks the problem, it's likely that either
                      >> the debugger is broken or you're dealing with undefined behavior.[/color]
                      >
                      > It is impossible for a debugger to mask itself completely.
                      > Having written a debugger for embedded systems I can tell you,
                      > the debugger is a BIG mess that comes upon your poor program.
                      >
                      > Impossible to do otherwise in cramped conditions, no RAM,
                      > no MMU, etc.
                      >
                      > That the program has "undefined behavior" is obvious, if not he
                      > would not be trying to debug !!![/color]

                      Not at all. All we know is that the program has incorrect behavior.
                      It could be the result of unspecified behavior, system-defined
                      behavior, or just an incorrect algorithm. The fact that using a
                      source level debugger changes the behavior makes it likely that the
                      problem is caused by undefined behavior, but it's still not certain.

                      --
                      Keith Thompson (The_Other_Keit h) kst-u@mib.org <http://www.ghoti.net/~kst>
                      San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
                      We must do something. This is something. Therefore, we must do this.

                      Comment

                      • Flash Gordon

                        #12
                        Re: Function invocation location

                        Keith Thompson wrote:

                        <snip>
                        [color=blue]
                        > If a source level debugger masks the problem, it's likely that either
                        > the debugger is broken or you're dealing with undefined behavior.[/color]

                        The arguably broken debugger is definitely one that happens in real
                        life. I've dealt with a processor where the only ICE and simulator both
                        broke the behaviour of the processor pipeline whenever the code hit a
                        breakpoint or when you single stepped. I considered it to be severely
                        broken, but there were no alternatives available.
                        [color=blue]
                        > You
                        > can do what you want by changing your code, but that's also likely to
                        > disturb things. (It's worth a try, though.)[/color]

                        Yes, definitely worth a try.
                        [color=blue]
                        > If you know how the compiler lays out stack frames, you *might* be
                        > able to display the return address in, say, hexadecimal, and map that
                        > back to the point at which the function was called. This is clearly
                        > *extremely* system-specific, so we can't really go into it here, but
                        > it might give you what you need.[/color]

                        Or the compiler might have an extension to do it, but as Keith says this
                        is highly system specific.
                        --
                        Flash Gordon
                        Living in interesting times.
                        Although my email address says spam, it is real and I read it.

                        Comment

                        • Flash Gordon

                          #13
                          Re: Function invocation location

                          jacob navia wrote:[color=blue]
                          > Keith Thompson a écrit :
                          > [snip]
                          >[color=green]
                          >> If a source level debugger masks the problem, it's likely that either
                          >> the debugger is broken or you're dealing with undefined behavior.[/color]
                          >
                          > It is impossible for a debugger to mask itself completely.[/color]

                          Not always the case except in terms hardware timings. Some In-Circuit
                          Emulators I have used, that come with high-level language debuggers, use
                          special versions of the chips that allow the ICE to stop the processor
                          dead and examine everything (including the internal registers) without
                          disturbing anything.
                          [color=blue]
                          > Having written a debugger for embedded systems I can tell you,
                          > the debugger is a BIG mess that comes upon your poor program.[/color]

                          Not always the case.
                          [color=blue]
                          > Impossible to do otherwise in cramped conditions, no RAM,
                          > no MMU, etc.[/color]

                          Not always the case, since the debugger may not even be running on the
                          same processor. See ICE above.
                          [color=blue]
                          > That the program has "undefined behavior" is obvious, if not he
                          > would not be trying to debug !!![/color]

                          No, it could be any kind of error, not necessarily undefined behaviour.
                          [color=blue][color=green]
                          >> You
                          >> can do what you want by changing your code, but that's also likely to
                          >> disturb things. (It's worth a try, though.)[/color]
                          >
                          > I agree with you in this. The printfs do CHANGE things, and even if
                          > the impact is smaller than the impact of the debugger, they DO CHANGE
                          > the program, as you said.[/color]

                          Indeed. Also, if it is an embedded system, sometimes a logic analyser is
                          the best tool.
                          [color=blue][color=green]
                          >> If you know how the compiler lays out stack frames, you *might* be
                          >> able to display the return address in, say, hexadecimal, and map that
                          >> back to the point at which the function was called. This is clearly
                          >> *extremely* system-specific, so we can't really go into it here, but
                          >> it might give you what you need.[/color]
                          >
                          > That is the best solution for this problem. Find out how the
                          > compiler lays out the stack frame (an assembly listing will do that)
                          > and try to send the hexadecimal return address through the serial
                          > line.[/color]

                          Check the documentation before reading the assembly output. There may be
                          extensions to help, or the documentation may tell you what the stack
                          layout is.
                          [color=blue]
                          > With the help of a link map, you can figure out where you were called from.[/color]

                          Not always that simple if there are dynamically loaded libraries, since
                          they might not always be loaded to the same address.
                          --
                          Flash Gordon
                          Living in interesting times.
                          Although my email address says spam, it is real and I read it.

                          Comment

                          • jacob navia

                            #14
                            Re: Function invocation location

                            Flash Gordon a écrit :[color=blue]
                            > jacob navia wrote:
                            >[color=green]
                            >> Keith Thompson a écrit :
                            >> [snip]
                            >>[color=darkred]
                            >>> If a source level debugger masks the problem, it's likely that either
                            >>> the debugger is broken or you're dealing with undefined behavior.[/color]
                            >>
                            >>
                            >> It is impossible for a debugger to mask itself completely.[/color]
                            >
                            >
                            > Not always the case except in terms hardware timings. Some In-Circuit
                            > Emulators I have used, that come with high-level language debuggers, use
                            > special versions of the chips that allow the ICE to stop the processor
                            > dead and examine everything (including the internal registers) without
                            > disturbing anything.
                            >[/color]

                            Well, that's a debugger with hardware assist. We do not all have
                            that luxury...

                            The debugger I wrote was for a chip that was designed and built around
                            a chip that offered 80K Ram, that could not be used for debugging,
                            and program memory (EPROM) that could not be altered. The compiler
                            would emit instructions at each line to test for a line breakpoints
                            array.

                            If the current line was found in the array, it would change
                            to a "server" mode that sent info to the PC debugger. HELL I can
                            tell you!
                            [color=blue][color=green]
                            >> Having written a debugger for embedded systems I can tell you,
                            >> the debugger is a BIG mess that comes upon your poor program.[/color]
                            >
                            >
                            > Not always the case.
                            >[/color]

                            Of course not. Maybe in the debuggers I wrote only :-) Or the debugger
                            writers are much more lucky, benefit from hardware assist, etc.
                            [color=blue][color=green]
                            >> Impossible to do otherwise in cramped conditions, no RAM,
                            >> no MMU, etc.[/color]
                            >
                            >
                            > Not always the case, since the debugger may not even be running on the
                            > same processor. See ICE above.
                            >[/color]

                            If your processor doesn't have any ICE or breakpoint instruction
                            the debugger becomes tricky even if the real debugger runs in a PC.
                            [color=blue][color=green]
                            >> That the program has "undefined behavior" is obvious, if not he
                            >> would not be trying to debug !!![/color]
                            >
                            >
                            > No, it could be any kind of error, not necessarily undefined behaviour.
                            >[/color]

                            Errors that disappear when the debugger steps in are mostly UB, except
                            of timing constraints.

                            Comment

                            • Flash Gordon

                              #15
                              Re: Function invocation location

                              jacob navia wrote:[color=blue]
                              > Flash Gordon a écrit :[color=green]
                              >> jacob navia wrote:
                              >>[color=darkred]
                              >>> Keith Thompson a écrit :
                              >>> [snip]
                              >>>
                              >>>> If a source level debugger masks the problem, it's likely that either
                              >>>> the debugger is broken or you're dealing with undefined behavior.
                              >>>
                              >>> It is impossible for a debugger to mask itself completely.[/color]
                              >>
                              >> Not always the case except in terms hardware timings. Some In-Circuit
                              >> Emulators I have used, that come with high-level language debuggers,
                              >> use special versions of the chips that allow the ICE to stop the
                              >> processor dead and examine everything (including the internal
                              >> registers) without disturbing anything.[/color]
                              >
                              > Well, that's a debugger with hardware assist. We do not all have
                              > that luxury...[/color]

                              Agreed. I fully accept that sometimes debuggers have to work within the
                              limitations you talked about, it's just not always the case.

                              Anyway, this is OT here, so I think we should drop it.

                              <snip>
                              [color=blue][color=green]
                              >> Not always the case, since the debugger may not even be running on the
                              >> same processor. See ICE above.[/color]
                              >
                              > If your processor doesn't have any ICE or breakpoint instruction
                              > the debugger becomes tricky even if the real debugger runs in a PC.[/color]

                              You can always write a complete emulation of the hardware and run the
                              emulation on a PC (or other powerful computer) which, of course,
                              potentially gives the debugger full control since the "processor" is
                              then part of the debugger rather than a real piece of HW :-)

                              I've seen it done and used such simulator debuggers, just a pittle the
                              ones I used were very badly written.
                              [color=blue][color=green][color=darkred]
                              >>> That the program has "undefined behavior" is obvious, if not he
                              >>> would not be trying to debug !!![/color]
                              >>
                              >> No, it could be any kind of error, not necessarily undefined behaviour.[/color]
                              >
                              > Errors that disappear when the debugger steps in are mostly UB, except
                              > of timing constraints.[/color]

                              I've come across many real world situations where there was no undefined
                              behaviour, but there was a timing issue. Or, as in the code I debugged
                              the day before yesterday, if something external responds too slowly the
                              code invokes undefined behaviour, but if you step through the code the
                              external event happens fast enough so you don't invoke undefined
                              behaviour. I identified the bug by the use of valgrind and code inspection.
                              --
                              Flash Gordon
                              Living in interesting times.
                              Although my email address says spam, it is real and I read it.

                              Comment

                              Working...