Why won't my shellcode (int3) be hit with the signal handler?
Apart from not like to have printf() in the handler, I care
for how to deliver the shellcode (as not inline assembler)
within the signal handler, being executed at runtime.
However, I present here a longer gdb session, that shows register
state and backtrace.
<code> Pid 19750 waiting for SIGUSR1 Program received signal SIGUSR1,
User defined signal 1. 0x0e5f9f89 in nanosleep () at <stdin>:2 2
<stdin>: No such file or directory.
in <stdin> Current language: auto; currently asm (gdb) bt
#0 0x0e5f9f89 in nanosleep () at <stdin>:2
#1 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
#2 0x18cb3d5b in main () at sig5.c:37 (gdb) i r eax 0x5b 91 ecx 0x0 0 edx 0xa 10 ebx
0x2e5df594 777909652 esp 0xcfbf73fc 0xcfbf73fc
ebp 0xcfbf7438 0xcfbf7438 esi 0x38cb62df
952853215 edi 0x38cb61e0 952852960 eip
0xe5f9f89 0xe5f9f89 eflags 0x206 518 cs
0x2b 43 ss 0x33 51 ds 0x33 51 es
0x33 51 fs 0x5b 91 gs 0x63 99
(gdb) c Continuing.
Program received signal SIGUSR1, User defined signal 1. 0x0e5f9f89 in
nanosleep () at <stdin>:2 2 in <stdin> (gdb) c Continuing.
Signal 30 from pid 0, should int3
Program received signal SIGSEGV, Segmentation fault. 0x18cb3c7a in
sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23 23
ret(); Current language: auto; currently c (gdb) bt
#0 0x18cb3c7a in sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23
#1 <signal handler called>
#2 0x0e5f9f89 in nanosleep () at <stdin>:2
#3 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
#4 0x18cb3d5b in main () at sig5.c:37 (gdb) i r eax 0xcfbf7305 -809536763 ecx 0x0 0 edx
0x0 0 ebx 0x38cb5124 952848676 esp
0xcfbf72e8 0xcfbf72e8 ebp 0xcfbf7310 0xcfbf7310
esi 0x38cb62df 952853215 edi 0x38cb61e0
952852960 eip 0x18cb3c7a 0x18cb3c7a eflags
0x10282 66178 cs 0x2b 43 ss 0x33 51
ds 0x33 51 es 0x33 51 fs
0x5b 91 gs 0x63 99 (gdb) bt full
#0 0x18cb3c7a in sigusr1 (signo=30, si=0xcfbf737c, data=0xcfbf7328) at sig5.c:23
code = "ëÌ"
ret = (int (*)()) 0xcfbf7305
#1 <signal handler called> No symbol table info available.
#2 0x0e5f9f89 in nanosleep () at <stdin>:2 No locals.
#3 0x0e650348 in sleep (seconds=10) at /usr/src/lib/libc/gen/sleep.c:45
rqt = {tv_sec = 10, tv_nsec = 0}
rmt = {tv_sec = 0, tv_nsec = 0}
#4 0x18cb3d5b in main () at sig5.c:37
sa = {__sigaction_u = {__sa_handler = 0x18cb3c04 <sigusr1>,
__sa_sigaction = 0x18cb3c04 <sigusr1>}, sa_mask = 0, sa_flags = 64}
-bash-4.3$ cat sig5.c
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
unsigned char code[] = \
"\xeb\xcc";
int (*ret)() = (int(*)())code;
printf("Signal %d from pid %lu, should int3\n", (int)si->si_signo,
(unsigned long)si->si_pid);
sleep (1);
ret();
exit(0); }
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0; } </code>
Any Ideas?
So this uses mprotect(), but still does not lead to the shell. We really need to update
radare2 shellcode sources :)
<code>
#include "errno.h"
#include "signal.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "sys/mman.h"
void sigusr1(int signo, siginfo_t *si, void *data) {
(void)signo;
(void)data;
unsigned char sc[] = \
"\xcc";
mprotect(sc,strlen(sc),PROT_EXEC|PROT_READ|PROT_WRITE);
int (*r)() = (int(*)())sc; /* Thanks, maybe change to define? */
r();
}
int main(void) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_flags = 5; /* SIGTRAP via Sil... */
sa.sa_sigaction = sigusr1;
if (sigaction(SIGUSR1, &sa, 0) == -1) {
fprintf(stderr, "%s: %s\n", "sigaction", strerror(errno));
}
printf("Pid %lu waiting for SIGUSR1\n", (unsigned long)getpid());
for (;;) {
sleep(10);
}
return 0;
}
</code>
Related
I've tried to execute a C program. And it has compiled right however when I execute the output binary, it displays:
[16] 70041 illegal hardware instruction ./create
So, I add -g option to look like this:
cc create.c $(pkg-config --cflags --libs cairo) -g -o create
And the C code:
#include <cairo.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
int main(void){
cairo_surface_t *surface;
cairo_t *cr;
int j=0;
char seq[5];
for(int i=0; i<=360; i+=4){
surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
cr = cairo_create(surface);
cairo_set_line_width (cr, 6.0);
cairo_arc( cr, 800/2, 600/2, (600/2)-50, 0, 2*M_PI );
cairo_stroke (cr);
cairo_set_source_rgb( cr, 0.2, 0.2, i/360 );
cairo_arc( cr, 800/2, 600/2, (600/2)-60, 0, i*(M_PI/180.0) );
cairo_stroke(cr);
j++;
if( j<10 ){ sprintf(seq, "%s%d%d", "seq", 0, j); } else { sprintf(seq, "%s%d", "seq", j); }
cairo_surface_write_to_png(surface, seq);
cairo_surface_destroy(surface);
}
cairo_destroy(cr);
return 0;
}
The purpose of above code is create a sequence of pngs pictures. But there isn't any warning at the output.
I include the lldb output:
(lldb) target create "create"
Current executable set to '/Users/rikky/Documents/C/Cairo/FirstDraw/create' (x86_64).
(lldb) l
7 int main(void){
8 cairo_surface_t *surface;
9 cairo_t *cr;
10 int j=0;
11 char seq[5];
12
13 for(int i=0; i<=360; i+=4){
14 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 800, 600);
15 cr = cairo_create(surface);
16 cairo_set_line_width (cr, 6.0);
(lldb) run
Process 70245 launched: '/Users/rikky/Documents/C/Cairo/FirstDraw/create' (x86_64)
Process 70245 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
frame #0: 0x00007fff6e80ffca libsystem_c.dylib`__chk_fail_overflow.cold.1 + 16
libsystem_c.dylib`__chk_fail_overflow.cold.1:
-> 0x7fff6e80ffca <+16>: ud2
libsystem_c.dylib`__chk_fail_overlap.cold.1:
0x7fff6e80ffcc <+0>: pushq %rbp
0x7fff6e80ffcd <+1>: movq %rsp, %rbp
0x7fff6e80ffd0 <+4>: leaq 0x6e41(%rip), %rdi ; "detected source and destination buffer overlap"
Target 0: (create) stopped.
I didn't understand the EXC_I386_INVOP code. Is there any way to fix it?
The Clang Version:
Apple clang version 12.0.0 (clang-1200.0.32.2)
Target: x86_64-apple-darwin19.6.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
Since my last system upgrade on Gentoo, I'm not able to run some code of mine: window_management.c which was working without any warnings nor errors before the upgrade.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <X11/XKBlib.h>
#include "common.h"
#include "extensions.h"
#include "text_pointer.h"
#include "window_management.h"
static void (*cursor_position_callback)(int xpos, int ypos) = 0;
void (*mouse_button_callback)(int xpos, int ypos, int button, int action) = 0;
#ifdef DSTUDIO_RELY_ON_X11
#define DSTUDIO_X11_INPUT_MASKS \
ExposureMask | \
KeyPressMask | \
KeyReleaseMask | \
ButtonPressMask | \
ButtonReleaseMask | \
VisibilityChangeMask
#define GLX_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define GLX_CONTEXT_MINOR_VERSION_ARB 0x2092
typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
static int ctx_error_occurred = 0;
static int window_alive = 1;
static int refresh_all = 1;
static Display *display = NULL;
static Window window;
static XVisualInfo * visual_info;
static Colormap color_map;
static XEvent x_event;
static XEvent x_sent_expose_event;
static GLXContext opengl_context;
static int visual_attribs[] = {
GLX_X_RENDERABLE , True,
GLX_DRAWABLE_TYPE , GLX_WINDOW_BIT,
GLX_RENDER_TYPE , GLX_RGBA_BIT,
GLX_X_VISUAL_TYPE , GLX_TRUE_COLOR,
GLX_RED_SIZE , 8,
GLX_GREEN_SIZE , 8,
GLX_BLUE_SIZE , 8,
GLX_ALPHA_SIZE , 8,
GLX_DEPTH_SIZE , 24,
GLX_STENCIL_SIZE , 8,
GLX_DOUBLEBUFFER , True,
None
};
static int glx_major, glx_minor;
static unsigned int keyboard_chars_map_mode = 0;
static int ctx_error_handler( Display *dpy, XErrorEvent *ev ) {
(void) dpy;
(void) ev;
ctx_error_occurred = 1;
return 0;
}
static void creating_color_map(XVisualInfo * vi, Window * root_window, XSetWindowAttributes * swa) {
color_map = XCreateColormap(display, *root_window, vi->visual, AllocNone);
swa->colormap = color_map;
swa->background_pixmap = None ;
swa->border_pixel = 0;
swa->event_mask = ExposureMask | StructureNotifyMask |PointerMotionMask;
}
void destroy_context() {
glXDestroyContext(display, opengl_context);
XDestroyWindow(display, window);
XCloseDisplay(display);
}
static void get_visual_info(GLXFBConfig * best_frame_buffer_config) {
int fbcount;
int best_frame_buffer_config_index = -1;
int worst_fbc = -1;
int best_num_samp = -1;
int worst_num_samp = 999;
GLXFBConfig * frame_buffer_config = glXChooseFBConfig(display, DefaultScreen(display), visual_attribs, &fbcount);
DSTUDIO_EXIT_IF_NULL(frame_buffer_config)
for (int i=0; i<fbcount; ++i) {
visual_info = glXGetVisualFromFBConfig( display, frame_buffer_config[i] );
if (visual_info) {
int samp_buf, samples;
glXGetFBConfigAttrib( display, frame_buffer_config[i], GLX_SAMPLE_BUFFERS, &samp_buf );
glXGetFBConfigAttrib( display, frame_buffer_config[i], GLX_SAMPLES , &samples );
#ifdef DSTUDIO_DEBUG
printf("Matching fbconfig %d, visual ID 0x%2lux: SAMPLE_BUFFERS = %d, SAMPLES = %d\n", i, visual_info->visualid, samp_buf, samples );
#endif
if ( best_frame_buffer_config_index < 0 || (samp_buf && samples > best_num_samp)) {
best_frame_buffer_config_index = i;
best_num_samp = samples;
}
if ( worst_fbc < 0 || !samp_buf || samples < worst_num_samp ) {
worst_fbc = i;
worst_num_samp = samples;
}
}
XFree(visual_info);
}
*best_frame_buffer_config = frame_buffer_config[ best_frame_buffer_config_index ];
XFree( frame_buffer_config );
// Get a visual
visual_info = glXGetVisualFromFBConfig( display, *best_frame_buffer_config );
#ifdef DSTUDIO_DEBUG
printf( "Chosen visual ID = 0x%lux\n", visual_info->visualid );
#endif
}
void init_context(const char * window_name, int width, int height) {
DSTUDIO_EXIT_IF_NULL(XInitThreads());
int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(&ctx_error_handler);
Window root_window;
XSetWindowAttributes swa;
XSizeHints * size_hints;
display = XOpenDisplay(NULL);
DSTUDIO_EXIT_IF_NULL(display)
DSTUDIO_EXIT_IF_NULL(glXQueryVersion( display, &glx_major, &glx_minor ))
DSTUDIO_EXIT_IF_FAILURE( glx_major == 1 && (glx_minor < 3))
DSTUDIO_EXIT_IF_FAILURE( glx_major < 1 )
GLXFBConfig best_frame_buffer_config;
get_visual_info(&best_frame_buffer_config);
DSTUDIO_EXIT_IF_NULL(visual_info)
root_window = RootWindow(display, visual_info->screen);
creating_color_map(visual_info, &root_window, &swa);
window = XCreateWindow(display, root_window, 0, 0, width, height, 0, visual_info->depth, InputOutput, visual_info->visual, CWBorderPixel|CWColormap|CWEventMask, &swa);
DSTUDIO_EXIT_IF_NULL(window)
size_hints = XAllocSizeHints();
size_hints->flags = PMinSize | PMaxSize;
size_hints->min_width = width;
size_hints->min_height = height;
size_hints->max_width = width;
size_hints->max_height = height;
XSetWMSizeHints(display, window, size_hints, XA_WM_NORMAL_HINTS);
Atom delWindow = XInternAtom(display, "WM_DELETE_WINDOW", 0);
XSetWMProtocols(display , window, &delWindow, 1);
XSelectInput(display, window, DSTUDIO_X11_INPUT_MASKS | ButtonMotionMask);
XkbSetDetectableAutoRepeat (display, 1, NULL);
XFree(visual_info);
XMapWindow(display, window);
XStoreName(display, window, window_name);
// Begin OpenGL context creation
const char *glx_exts = glXQueryExtensionsString(display, DefaultScreen( display ));
glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
if ( !is_extension_supported( glx_exts, "GLX_ARB_create_context" ) || !glXCreateContextAttribsARB ) {
#ifdef DSTUDIO_DEBUG
printf("glXCreateContextAttribsARB() not found. Using old-style GLX context.\n");
#endif
opengl_context = glXCreateNewContext( display, best_frame_buffer_config, GLX_RGBA_TYPE, 0, 1);
}
else {
int context_attribs[] = {
GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
GLX_CONTEXT_MINOR_VERSION_ARB, 3,
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
//GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
None
};
opengl_context = glXCreateContextAttribsARB(display, best_frame_buffer_config, 0, 1, context_attribs);
}
// Sync to ensure any errors generated are processed.
XSync(display, 0);
DSTUDIO_EXIT_IF_FAILURE( ctx_error_occurred && opengl_context == 0)
XSetErrorHandler(old_handler);
#ifdef DSTUDIO_DEBUG
if (!glXIsDirect(display, opengl_context)) {
printf("Indirect GLX rendering context obtained\n");
}
else {
printf("Direct GLX rendering context obtained\n");
}
#endif
glXMakeCurrent( display, window, opengl_context );
}
void send_expose_event() {
memset(&x_sent_expose_event, 0, sizeof(x_sent_expose_event));
x_sent_expose_event.xexpose.serial = clock();
x_sent_expose_event.type = Expose;
x_sent_expose_event.xexpose.send_event = 1;
x_sent_expose_event.xexpose.display = display;
XSendEvent(display, window, 1, ExposureMask, &x_sent_expose_event);
XFlush(display);
}
void swap_window_buffer() {
glXSwapBuffers(display, window);
}
#endif
My code crash when calling glXSwapBuffers() with the following output:
X Error of failed request: BadMatch (invalid parameter attributes)
Major opcode of failed request: 130 (MIT-SHM)
Minor opcode of failed request: 3 (X_ShmPutImage)
Serial number of failed request: 52
Current serial number in output stream: 53
I noticed that glxgears have similar issue on my box, but doesn't crash. The error came out only when exiting glxgears and produce the following:
X Error of failed request: BadDrawable (invalid Pixmap or Window parameter)
Major opcode of failed request: 130 (MIT-SHM)
Minor opcode of failed request: 3 (X_ShmPutImage)
Resource id in failed request: 0x2600002
Serial number of failed request: 912
Current serial number in output stream: 913
I first tried to recompile my kernel, xorg-drivers, xorg-server, mesa and xf86-video-intel (Yeah I'm on an Intel third generation) without any progress.
Since glxgears run "fine" and even if it might be a bug in the above packages, maybe there is something i'm doing wrong here.
EDIT 1: As suggested in comments, I've compiled my code with -fsanitize=address and got the following output:
=================================================================
==8391==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 2048 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x55c7722b61e1 in load_shader /home/http/dev/github/DStudio/src/ui.c:357
#2 0x55c7722b3fb9 in create_shader_program /home/http/dev/github/DStudio/src/ui.c:113
#3 0x55c7722ab509 in ui_thread /home/http/dev/github/DStudio/src/dsandgrains/ui.c:305
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 600 byte(s) in 5 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x7fa745c9371e in __getdelim (/lib64/libc.so.6+0x7571e)
#2 0x55c7722af580 in get_proc_memory_usage /home/http/dev/github/DStudio/src/fileutils.c:119
#3 0x55c7722b1a42 in update_system_usage /home/http/dev/github/DStudio/src/system_usage.c:71
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 600 byte(s) in 5 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x7fa745c9371e in __getdelim (/lib64/libc.so.6+0x7571e)
#2 0x55c7722af580 in get_proc_memory_usage /home/http/dev/github/DStudio/src/fileutils.c:119
#3 0x55c7722b196f in update_system_usage /home/http/dev/github/DStudio/src/system_usage.c:56
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 120 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x7fa745c9371e in __getdelim (/lib64/libc.so.6+0x7571e)
#2 0x55c7722afa87 in set_physical_memory /home/http/dev/github/DStudio/src/fileutils.c:169
#3 0x55c7722a693b in main /home/http/dev/github/DStudio/src/dsandgrains/main.c:36
#4 0x7fa745c41e6a in __libc_start_main (/lib64/libc.so.6+0x23e6a)
Direct leak of 80 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669da68 in __interceptor_calloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10ca68)
#1 0x55c7722b7e7b in init_context /home/http/dev/github/DStudio/src/window_management.c:172
#2 0x55c7722ab4b5 in ui_thread /home/http/dev/github/DStudio/src/dsandgrains/ui.c:295
#3 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
Direct leak of 16 byte(s) in 1 object(s) allocated from:
#0 0x7fa74669d878 in __interceptor_malloc (/usr/lib/gcc/x86_64-pc-linux-gnu/9.2.0/libasan.so.5+0x10c878)
#1 0x55c7722b5242 in init_ui_elements /home/http/dev/github/DStudio/src/ui.c:246
#2 0x55c7722a96a0 in init_ui /home/http/dev/github/DStudio/src/dsandgrains/ui.c:154
#3 0x55c7722ab513 in ui_thread /home/http/dev/github/DStudio/src/dsandgrains/ui.c:307
#4 0x7fa7462bf457 in start_thread (/lib64/libpthread.so.0+0x8457)
SUMMARY: AddressSanitizer: 3464 byte(s) leaked in 14 allocation(s).
Following program generates SIGSEGV from within SIGUSR1 signal handler.
#include <signal.h>
#include <unistd.h>
#include <iostream>
void sigusr_handler(int sig_number)
{
std::cout << "hallo" << "\n";
char *a = (char*)0x0;
char b = *a;
std::cout << b << "\n";
}
struct sigaction my_action;
int main(int argc, char *argv[])
{
my_action.sa_handler = sigusr_handler;
sigaction(SIGUSR1, &my_action, nullptr);
sleep(1000);
return 0;
}
Let's run program in gdb then send SIGUSR1 to the program.
siginfo looks like following
(gdb) p $_siginfo
$8 = {
si_signo = 11,
si_errno = 0,
si_code = 1,
_sifields = {
_pad = {0, 0, -1814214640, 21880, -1601342336, 32766, -1848922720, 21880, -1811928400, 21880, 0, 0, -1811928400, 21880, 176, 0, -1840786848, 21880, -1847783957, 21880, -1811928400, 21880, -1840786848, 21880, -1814214640, 21880, -1845891081, 21880},
_kill = {
si_pid = 0,
si_uid = 0
},
_timer = {
si_tid = 0,
si_overrun = 0,
si_sigval = {
sival_int = -1814214640,
sival_ptr = 0x557893dd4810
}
},
_rt = {
si_pid = 0,
si_uid = 0,
si_sigval = {
sival_int = -1814214640,
sival_ptr = 0x557893dd4810
}
},
_sigchld = {
si_pid = 0,
si_uid = 0,
si_status = -1814214640,
si_utime = -6877712962820221576,
si_stime = -7941062615231332354
},
_sigfault = {
si_addr = 0x0,
_addr_lsb = 93976365189136,
_addr_bnd = {
_lower = 0x7ffea08d7480,
_upper = 0x557891cbada0
}
},
_sigpoll = {
si_band = 0,
si_fd = -1814214640
}
}
}
Question: is it possible to "guess" from gdb session, that outer signal was SIGUSR1?
regards,
Mat
NOTE TO STACKOVEFLOW: I have no idea what usefull notes I need to add to the above in order to have the question more usefull - IMO: more text makes the question blurred, but I'm adding some notes because I'm getting information:
"It looks like your post is mostly code; please add some more details" otherwise.
READERS OF POST: PLEASE FORGIVE ME.
END OF NOTE TO STACKOVERFLOW
is it possible to "guess" from gdb session, that outer signal was SIGUSR1
Yes:
hallo
Program received signal SIGSEGV, Segmentation fault.
0x00005555555551be in sigusr_handler (sig_number=10) at t.c:9
9 char b = *a;
(gdb) bt
#0 0x00005555555551be in sigusr_handler (sig_number=10) at t.c:9
#1 <signal handler called>
#2 0x00007ffff775cff4 in __GI___nanosleep (requested_time=requested_time#entry=0x7fffffffdb70, remaining=remaining#entry=0x7fffffffdb70)
at ../sysdeps/unix/sysv/linux/nanosleep.c:28
#3 0x00007ffff775cf2a in __sleep (seconds=0) at ../sysdeps/posix/sleep.c:55
#4 0x0000555555555225 in main (argc=1, argv=0x7fffffffdca8) at t.c:20
From this, you can clearly see that the program received SIGSEGV while in the handler for signal 10, which is SIGUSR1.
P.S. It's unclear how this question even arises: GDB should have earlier stopped and told you that SIGUSR1 was received, like so:
Program received signal SIGUSR1, User defined signal 1.
0x00007ffff775cff4 in __GI___nanosleep (requested_time=requested_time#entry=0x7fffffffdb70, remaining=remaining#entry=0x7fffffffdb70) at ../sysdeps/unix/sysv/linux/nanosleep.c:28
28 ../sysdeps/unix/sysv/linux/nanosleep.c: No such file or directory.
I try to get the backtrace of all threads of a process.
I wrote a test program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int func_a(int *a)
{
*a++;
return 0;
}
void* test_thread(void* args)
{
int a = 0;
while(1) {
func_a(&a);
//sleep(1);
}
fprintf(stdout, "%d\n", a);
return NULL;
}
int main(int argc, char **argv)
{
pthread_t pid = 0;
pthread_create(&pid, NULL, test_thread, NULL);
pthread_create(&pid, NULL, test_thread, NULL);
pthread_create(&pid, NULL, test_thread, NULL);
pause();
return 0;
}
then i ran the program,and execute
pidof ./1|xargs -n1 sudo gdb --batch -ex "thread apply all bt full" -p
I saw the backtrace.(too many output i just pick some)
Thread 2 (Thread 0xb459db40 (LWP 25272)):
#0 func_a (a=0xb459d354) at 1.c:6
No locals.
#1 0x0804871f in test_thread (args=0x0) at 1.c:21
a = 382337846
#2 0xb775bf72 in start_thread (arg=0xb459db40) at pthread_create.c:312
__res = <optimized out>
pd = 0xb459db40
now = <optimized out>
unwind_buf = {cancel_jmp_buf = {{jmp_buf = {-1216946176, -1269179584, 4001536, -1269181400, -56721544, -1538858626}, mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
not_first_call = <optimized out>
pagesize_m1 = <optimized out>
sp = <optimized out>
freesize = <optimized out>
__PRETTY_FUNCTION__ = "start_thread"
#3 0xb7691f8e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:129
No locals.
But when I enable the sleep statement in test_thread function,it can't get the backtrace.
Thread 3 (Thread 0xb4d29b40 (LWP 26045)):
#0 0xb7716cf9 in ?? ()
No symbol table info available.
#1 0x00000000 in ?? ()
No symbol table info available.
Thread 2 (Thread 0xb4528b40 (LWP 26046)):
#0 0xb7716cf9 in ?? ()
No symbol table info available.
#1 0x00000000 in ?? ()
No symbol table info available.
does anyone know why
thanks #Employed Russian to point out the defects.The enviroment is as follow:
gcc version: 4.8.4
gdb version: 7.7.1
compile command: gcc -g 1.c -o 1 -lpthread -rdynamic
~/.gdbinit is not exist
I use ubuntu 14.04
I am using gdb to debug a code that starts a timer. When the timer rings in gdb I always end up at instruction timer_settime+16.
Is this expected behavior?
As an example I slightly modified the code of timer_settime man page. The idea is to pass two arguments: a string of integers and a nsec value. The code launches the timer to ring after nsec, then copies the string.
I expected that by incrementing the nsec value, gdb stopped at different code lines, to end up inside the copy loop. However it always stops at .
So is this expected behavior?
Is it documented somewhere?
Is there a way to achieve what I expected (i.e.: launch a timer that when ring makes gdb stops where the program was just before (or after) the signal)? (always with nsec granularity).
Code:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
#include <time.h>
#define CLOCKID CLOCK_REALTIME
#define SIG SIGUSR1
#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)
unsigned char OUT[32];
unsigned char IN[32];
unsigned char ascii2hex(char in){
unsigned char out;
if( ('0' <= in) && (in <= '9') )
out = in - '0';
if( ('A' <= in) && (in <= 'F') )
out = in - 'A' + 10;
if( ('a' <= in) && (in <= 'f') )
out = in - 'a' + 10;
return out;
}
void asciiStr2hex(char * in, unsigned char * out, unsigned int len){
int i = 0;
int j = 0;
for( i = 0; i < len; i+=2){
out[j++] = (ascii2hex(in[i ]) << 4) + ascii2hex(in[i+1]);
}
}
void testcode(unsigned char *out, unsigned char *in, unsigned int len){
unsigned int i;
for (i=0;i<len;i++)
out[i] = in[i];
}
static void print_siginfo(siginfo_t *si)
{
timer_t *tidp;
int or;
tidp = si->si_value.sival_ptr;
printf(" sival_ptr = %p; ", si->si_value.sival_ptr);
printf(" *sival_ptr = 0x%lx\n", (long) *tidp);
or = timer_getoverrun(*tidp);
if (or == -1)
errExit("timer_getoverrun");
else
printf(" overrun count = %d\n", or);
}
static void handler(int sig, siginfo_t *si, void *uc)
{
/* Note: calling printf() from a signal handler is not
strictly correct, since printf() is not async-signal-safe;
see signal(7) */
printf("Caught signal %d\n", sig);
print_siginfo(si);
signal(sig, SIG_IGN);
}
int main(int argc, char *argv[])
{
timer_t timerid;
struct sigevent sev;
struct itimerspec its;
long long freq_nanosecs;
//sigset_t mask;
struct sigaction sa;
if (argc != 3) {
fprintf(stderr, "Usage: %s <16byte> <time-nanosecs>\n",
argv[0]);
exit(EXIT_FAILURE);
}
asciiStr2hex(argv[1], IN, 32);
/* Establish handler for timer signal */
printf("Establishing handler for signal %d\n", SIG);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
sigemptyset(&sa.sa_mask);
if (sigaction(SIG, &sa, NULL) == -1)
errExit("sigaction");
/* Block timer signal temporarily */
/* printf("Blocking signal %d\n", SIG);
sigemptyset(&mask);
sigaddset(&mask, SIG);
if (sigprocmask(SIG_SETMASK, &mask, NULL) == -1)
errExit("sigprocmask");
*/
/* Create the timer */
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = SIG;
sev.sigev_value.sival_ptr = &timerid;
if (timer_create(CLOCKID, &sev, &timerid) == -1)
errExit("timer_create");
printf("timer ID is 0x%lx\n", (long) timerid);
/* Start the timer */
freq_nanosecs = atoll(argv[2]);
its.it_value.tv_sec = freq_nanosecs / 1000000000;
its.it_value.tv_nsec = freq_nanosecs % 1000000000;
its.it_interval.tv_sec = its.it_value.tv_sec;
its.it_interval.tv_nsec = its.it_value.tv_nsec;
if (timer_settime(timerid, 0, &its, NULL) == -1)
errExit("timer_settime");
/* Sleep for a while; meanwhile, the timer may expire
multiple times */
printf("Sleeping for %d seconds\n", atoi(argv[1]));
testcode(OUT, IN, 16);
/* Unlock the timer signal, so that timer notification
can be delivered */
/* printf("Unblocking signal %d\n", SIG);
if (sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1)
errExit("sigprocmask");
*/
exit(EXIT_SUCCESS);
}
When debug into gdb with r 00112233445566778899001122334455 2
I obtain:
Program received signal SIGUSR1, User defined signal 1.
0x76fc7c38 in timer_settime () from /lib/arm-linux-gnueabihf/librt.so.1
(gdb) x/30i $pc
=> 0x76fc7c38 <timer_settime+16>: cmn r0, #4096 ; 0x1000
0x76fc7c3c <timer_settime+20>: mov r4, r0
0x76fc7c40 <timer_settime+24>: bhi 0x76fc7c4c <timer_settime+36>
0x76fc7c44 <timer_settime+28>: mov r0, r4
0x76fc7c48 <timer_settime+32>: pop {r3, r4, r7, pc}
0x76fc7c4c <timer_settime+36>: bl 0x76fc55b4
0x76fc7c50 <timer_settime+40>: rsb r3, r4, #0
0x76fc7c54 <timer_settime+44>: mvn r4, #0
0x76fc7c58 <timer_settime+48>: str r3, [r0]
0x76fc7c5c <timer_settime+52>: b 0x76fc7c44 <timer_settime+28>
0x76fc7c60 <timer_settime+56>: andeq r0, r0, r2, lsl #2
0x76fc7c64: push {r4, r5, r6, r7, r8, r9, r10, lr}
0x76fc7c68: sub sp, sp, #600 ; 0x258
0x76fc7c6c: ldr r4, [pc, #340] ; 0x76fc7dc8
0x76fc7c70: add r1, sp, #512 ; 0x200
0x76fc7c74: add r4, pc, r4
0x76fc7c78: mov r0, r4
0x76fc7c7c: bl 0x76fc56b0
0x76fc7c80: cmp r0, #0
0x76fc7c84: bne 0x76fc7c98
0x76fc7c88: ldr r2, [sp, #512] ; 0x200
0x76fc7c8c: ldr r3, [pc, #312] ; 0x76fc7dcc
0x76fc7c90: cmp r2, r3
0x76fc7c94: beq 0x76fc7d94
0x76fc7c98: ldr r5, [pc, #304] ; 0x76fc7dd0
0x76fc7c9c: ldr r0, [pc, #304] ; 0x76fc7dd4
0x76fc7ca0: add r5, pc, r5
0x76fc7ca4: add r0, pc, r0
0x76fc7ca8: mov r1, r5
0x76fc7cac: bl 0x76fc5524
I am running such code on a raspberry pi, but I'am pretty sure I had the same behavior on another linux machine x86_64.
I have tested with "handle stop SIGUSR1".
I finally found that the problem was that I have to set unwindonsignal off in gdb to obtain the behavior I expected.