A simple, consistent, and portable way to include tracking and return to C

GNU libc backtrace and In-circuit emulators / debuggers are not always available when porting code to a new platform, especially when the target is a C microcomputer , such as for the Z80 . (Typically, a program error “just hung” somewhere or reset the gadget.)

Is there an alternative to the classic " wolf fencing " printf manual insert method? Something simple and portable (without the use of C-extensions) that an encoder can do when developing a program that includes tracing and backtracking in a C program?

BTW: Here are a few other /qaru.site / ... questions that are related, but both of them use the GNU GLIBC backtrace and backtrace are often compiler / implementation specific:

+3
source share
3 answers

There is an implementation of RosettaCode.org that uses the same basic idea as the @ jsl4tv proposal.

An example, given the following classic C code with built-in “hang”:

#include <stdio.h>
#include <stdlib.h>

void inner(int k)
{
   for(;;){} /* hang */
}

void middle(int x, int y)
{
  inner(x*y);
}

void outer(int a, int b, int c)
{
  middle(a+b, b+c);
}

int main()
{
  outer(2,3,5);
  return(EXIT_SUCCESS);
}

#define STACK_TRACE_ON #include "stack_trace.h" RosettaCode.org, BEGIN (f)/END, :

#include <stdio.h>
#include <stdlib.h>

#define STACK_TRACE_ON /* compile in these "stack_trace" routines */
#include "stack_trace.h"

void inner(int k)
BEGIN(inner)
   print_indent(); printf("*** Now dump the stack ***\n");
   print_stack_trace();
   for(;;){} /* hang */
END

void middle(int x, int y)
BEGIN(middle)
  inner(x*y);
END

void outer(int a, int b, int c)
BEGIN(outer)
  middle(a+b, b+c);
END

int main()
BEGIN(main)
  stack_trace.on = TRUE; /* turn on runtime tracing */
  outer(2,3,5);
  stack_trace.on = FALSE;
  RETURN(EXIT_SUCCESS);
END

:

stack_trace_test.c:19: BEGIN outer[0x80487b4], stack(depth:1, size:60)
stack_trace_test.c:14:   BEGIN middle[0x8048749], stack(depth:2, size:108)
stack_trace_test.c:8:     BEGIN inner[0x80486d8], stack(depth:3, size:156)
stack_trace_test.c:8:       *** Now dump the stack ***
stack_trace_test.c:8:   inner[0x80486d8]        --- stack(depth:4, size:156) ---
stack_trace_test.c:14:  middle[0x8048749]       --- stack(depth:3, size:108) ---
stack_trace_test.c:19:  outer[0x80487b4]        --- stack(depth:2, size:60) ---
stack_trace_test.c:24:  main[0x804882a] --- stack(depth:1, size:0) ---
stack_trace_test.c:8:       --- (depth 4) ---

BEGIN ~ END . (Esp, "FINALLY" ).

/URL .

+2

​​ : .

: locals , ...

, , , , , .

typedef struct stack_debug_blob_ {
    int magic1;
    const char * function_name;
    int magic2;
    struct stack_debug_blob_ * called_by;
    int magic3;
} stack_debug_blob;

stack_debug_blob * top_of_stack_debug_blobs = 0;

ENTER (f), . {. (const) char *, , , . blob .

#define ENTER(f)                                                \
stack_debug_blob new_stack_debug_blob = {                       \
    MAGIC1, (f), MAGIC2, top_of_stack_debug_blobs, MAGIC3};     \
stack_debug_blob * evil_hack = (top_of_stack_debug_blobs = (&new_stack_debug_blob))

, , ENTER, . , evil_hack , .

, blobs . (, stderr, , while (1) {/* nada */}, , ... ), .

EXIT(), blobs, . .

#define EXIT() do {                                            \
    check_debug_blobs();                                       \
    top_of_stack_debug_blobs = new_stack_debug_blob.called_by; \
    new_stack_debug_blob.magic1 -= 1; /* paranoia */           \
} while (0)

, RETURN, RETURN EXIT, } while (0).

, blobs, , - stacktrace backtrace.

ENTER (f) EXIT() RETURN (x).

, ...

. , backtrace uclibc?

+4

Symbian , , , , .

, . , ... , Z80! ..

To calculate the back trace from the stack without frame pointers, you need to process the stack, not down.

0
source

Source: https://habr.com/ru/post/1755153/


All Articles