In GDB I get a segmentation fault if I attempt to do the following:
print bg->top
The code looks a bit like this:
#interface Sprite : Object
{
#public
int top;
/* Other fields */
}
#end
bg = [Sprite load: "test.png"];
/* GDB is at a breakpoint after the above line */
The message I get is:
(gdb) print bg->top
Program received signal SIGSEGV, Segmentation fault.
0x6a7e3048 in libobjc-2!__objc_class_links_resolved () from C:\MinGW\bin\libobjc-2.dll
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on".
Evaluation of the expression containing the function
(objc_lookup_class) will be abandoned.
When the function is done executing, GDB will silently stop.
Why is this?
I'm using the GNU Objective-C runtime and I'm not using GNUStep.
how is 'bg' declared?
id bg or Sprite *bg
using 'id bg'
you must cast bg to the correct class,
(gdb) p bg->top
There is no member named top.
(gdb) p ((struct Sprite *)bg)->top
$1 = 0
using Sprite *bg
(gdb) p bg->top
$1 = 0
using GNU gdb (GDB) 7.3.50.20110421-cvs
under linux, which version of gdb are you using?
is the Sprite class implemented separately in a DLL/library or
in the main application?
its possible it could be some manifestation of
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=39465
Related
Consider the following Pseudo-C code:
static int G = 0;
void alrm_handler(int signo) {
G = 1;
}
void son() {
struct sched_param param;
param.sched_priority = 50;
sched_setscheduler(getpid(),SCHED_FIFO, ¶m);
kill(getppid(), SIG_ALRM);
sched_yield();
printf("A\n");
while(1);
exit(0);
}
int main() {
signal(SIG_ALRM, alrm_handler);
int son_pid = fork();
if(son_pid==0)
son();
waitpid(son_pid);
printf("B\n");
return 0;
}
It's from an exam in OS. The question is as follows:
In multi cores CPU what would be printed?
The answers is that we can't know because it could be A and then B or B and then A. I don't understand why. If parent is waiting for the son with waitpid and the son sends signal SIG_ALRM which invokes the alrm_handler function for the parent, the parent will finish executing the function and then return to waiting the son until he will finish running, no? So it should be A and then B.
According to POSIX it is undefined whether system calls are restarted after a signal handler set by signal is called.
System V and the Linux signal system call do not restart system calls.
BSD and by default GLibc, do restart system calls.
If System V signal is used waitpid can return as soon the signal has been sent, allowing the letters to be printed in any order. If standard output is a pipe or regular file only B will be output as the child is in a infinite loop
With BSD signal only A will be printed as waitpid does not return due to the infinite loop in the child. If standard output is a pipe or regular file only nothing will be output.
I am trying to count the number of calls to malloc using a Pintool. I am using Pin3.6/source/tools/ManualExamples/malloc_mt.cpp as a reference. All my instrumentation does is looks for malloc definition when an image is loaded and inserts a print before the call to malloc.
I am testing it with the below small program I wrote.
My problem is that the call to malloc seems to be happening twice according to the tool whereas I am calling it just once in my test program.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *p;
p = malloc(0xfff);
free(p);
}
On instrumenting this prints:
thread 0 entered main called from main of img /home/---/workspace/hw4/tst_progs/test
thread 0 entered malloc(4095) called from __libc_malloc of img /lib/i386-linux-gnu/libc.so.6
thread 0 entered malloc(4095) called from __libc_malloc of img /lib/i386-linux-gnu/libc.so.6
thread 0 entered malloc(1024) called from __libc_malloc of img /lib/i386-linux-gnu/libc.so.6
Any suggestions?
I'm trying to debug a program that I do not have the source for on Mac OS X. I would like to know what arguments it is calling gettattrlist() with, and inspect the return value, for two different volumes (in order to compare and see why it will let you use one volume and not the other).
I first tried dtruss; but that's useless for getattrlist(); it shows only the pointers that are being passed into getattrlist() (and doesn't even know how many arguments getattrlist() takes).
635/0x1dc5: getattrlist("/Volumes/MyVolume\0", 0x113FA6380, 0x113FA5FD0) = 0 0
635/0x1dc5: getattrlist("/Volumes/MyVolume\0", 0x113FA4F00, 0x113FA4B30) = 0 0
635/0x1dc5: getattrlist("/Volumes/MyVolume\0", 0x113FA5870, 0x113FA54C0) = 0 0
635/0x19c6: getattrlist("/Volumes/MyVolume\0", 0x7FFF5FBF9140, 0x7FFF5FBF8D70) = 0 0
635/0x19c6: getattrlist("/Volumes/MyVolume\0", 0x7FFF5FBFA8A0, 0x7FFF5FBFA4F0) = 0 0
So I tried GDB. I can set an unconditional breakpoint on getattrlist(), and take a look at its first argument, but it's called way too often for that to be useful.
(gdb) break getattrlist
Breakpoint 1 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Breakpoint 1, 0x00007fff8e90b6ac in getattrlist ()
(gdb) p (char *)$rdi
$1 = 0x7fff5fbfd67e "/some/random/path"
So, I probably need a conditional breakpoint, that will break only when the first argument matches the path I'm interested in. That shouldn't be too hard, right?
(gdb) delete
Delete all breakpoints? (y or n) y
(gdb) break getattrlist if ((int)strcmp((char *)$rdi, "/Volumes/My Volume")) == 0
Breakpoint 2 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Error in testing breakpoint condition:
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Breakpoint 2, 0x00007fff8e90b6ac in getattrlist ()
(gdb) p (char *)$rdi
$12 = 0x7fff5fbfd67e "/some/other/random/path"
What's this? GDB has ignored my condition because it suspects that it might call malloc() or the ObjC runtime? OK, well, strcmp() shouldn't call malloc(); it should just compare the strings byte by byte until it gets to a null character. So lets set that option the message recommends to override the check:
(gdb) set objc-non-blocking-mode off
(gdb) cont
Continuing.
Segmentation fault: 11
No dice. GDB and the application both die.
Any suggestions on how to set a conditional watchpoint on a string from GDB without running into this issue? Or other ways of capturing the arguments and return values (which are stored via an output argument) of getattrlist(), that works better than dtruss()?
Edit
Tried matt's solution, but no luck:
(gdb) set $vol = (char *) malloc((int)strlen("/Volumes/My Volume") + 1)
(gdb) call (int)strcpy($vol, "/Volumes/My Volume")
$1 = 236411760
(gdb) break getattrlist if ((int)strcmp((char *)$rdi, $vol)) == 0
Breakpoint 1 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Unsafe to run code: malloc zone lock is held for some zone..
Error in testing breakpoint condition:
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Breakpoint 1, 0x00007fff8e90b6ac in getattrlist ()
(gdb) p (char *)$rdi
$4 = 0x11a715838 "/some/other/random/path"
I decided to try memcmp() instead of strcmp(); no luck there either:
(gdb) break getattrlist if ((int)memcmp((char *)$rdi, $vol, 18)) == 0
Breakpoint 1 at 0x7fff8e90b6ac
(gdb) cont
Continuing.
Unsafe to run code: malloc zone lock is held for some zone..
Error in testing breakpoint condition:
Canceling call as the malloc lock is held so it isn't safe to call the runtime.
Issue the command:
set objc-non-blocking-mode off
to override this check if you are sure your call doesn't use the malloc libraries or the ObjC runtime.
Breakpoint 1, 0x00007fff8e90b6ac in getattrlist ()
(gdb)
At this point, I figured "OK, now there really shouldn't be anything using malloc()", so I decided to try set objc-non-blocking-mode off again. Still no luck:
(gdb) set objc-non-blocking-mode off
(gdb) cont
Continuing.
Reading symbols for shared libraries ... done
Reading symbols for shared libraries . done
Reading symbols for shared libraries ....... done
[Switching to process 5456 thread 0x2971b]
[Switching to process 5456 thread 0x29e2f]
warning: Unable to restore previously selected frame.
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
[Switching to process 5456 thread 0x29e2f]
0x0000000000000000 in ?? ()
Error in testing breakpoint condition:
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (memcmp) will be abandoned.
Breakpoint 1, 0x0000000000000000 in ?? ()
Error in testing breakpoint condition:
The program being debugged was signaled while in a function called from GDB.
GDB remains in the frame where the signal was received.
To change this behavior use "set unwindonsignal on"
Evaluation of the expression containing the function (memcmp) will be abandoned.
Breakpoint 1, 0x0000000000000000 in ?? ()
Hmm. What state am I in?
(gdb) bt
#0 0x0000000000000000 in ?? ()
#1 0x000000011e6ec070 in ?? ()
Ick. That doesn't look good. What if I continue here?
(gdb) cont
Continuing.
[Switching to process 5456 thread 0x2971b]
(gdb) bt
#0 0x00007fff8e90b6ac in getattrlist ()
#1 0x00007fff897c9c4b in GetPathVolFSAttributes ()
#2 0x00007fff897c9459 in PathGetObjectInfo ()
#3 0x00007fff897c9279 in FSPathMakeRefInternal ()
#4 0x00007fff8767b3ee in FSNodePrepareFSRef ()
... snip ...
(gdb) p (char *)$rdi
$2 = 0x10db1c2b0 "/System/Library/CoreServices/CoreTypes.bundle"
Nope. Still not actually breaking on the correct call to getattrlist(); and everything has died in the meantime due to the null pointer dereference.
I believe that something like the following should work.
(gdb) start
...
(gdb) set $x = malloc(strlen("foobar") + 1)
(gdb) call strcpy($x, "foobar")
(gdb) break a_leg if strcmp(foo, $x) == 0
In recent versions of GDB:
(gdb) start
(gdb) break a_leg if $_streq(foo, "foobar")
I'm not sure in what version this was introduced, but it's at least present in 7.7.1.
I have had success getting my debug builds to stop execution when a condition is programmatically specified, using the standard NSAssert(condition_which_should_evaluate_true, #"error message") statement in Objective C, and adding in an "All Exceptions" breakpoint in the Breakpoint Navigator.
Well and good, but most of the time when I'm debugging, I'd also like to continue normal program execution after that point. Often continuing the program after a failed assertion helps to track down the source of the confusion/bug. At least as far as I remember when I was programming on a different platform.
Is there a standard way to do so in Objective C development?
There's a way. It's not an Objective-C thing, it's a Unix thing.
kill(getpid(), SIGSTOP);
or simply:
raise(SIGSTOP);
In Swift:
raise(SIGSTOP)
This will break in the debugger in the __kill or __pthread_kill function. You will need to then go up a few stack frames to look at the frame that called kill or raise. You can use the debugger`s continue command to resume execution.
Note that if you're not running under the debugger and you execute this, your app will just hang. Take a look at [Technical Q&A QA1631: Detecting the Debugger](http://developer.apple.com/library/mac/#qa/qa1361/_index.html. You can use that information to write a wrapper function or macro that only sends SIGSTOP when running under the debugger. This answer may help.
Also, the Foundation framework provides a different assert macro for use in regular functions. It's NSCAssert.
Sounds like you want to use Conditional Breakpoints. If you set a breakpoint by clicking in the margin of your source code, then ctrl-click the little blue breakpoint thing, you can edit some options, including making the breakpoint conditional on the value of a variable.
Here's a blog post with some screenshots and more info.
This Stack Overflow question has some good pointers, too.
If you insist on triggering the breakpoint programmatically, then write a function and put a breakpoint inside it:
void MyConditionalBreak(BOOL condition, NSString *comment)
{
if (condition) {
NSLog(#"Stopped because %#", comment); // SET BREAKPOINT ON THIS LINE
}
}
Then you can call this function in a similar manner to NSAssert. If you declare the function in your project's precompiled header file (Whatever.pch) it will be available in all of your source files, without having to explicitly #import anything.
Here is how I do it:
First, in breakpoints tab I set my apps to break if any exception is raised:
Then In code (I usually have common header file containing common definitions like this that I import everywhere):
static void ThrowException(NSString* reason)
{
#try
{
#throw [NSException
exceptionWithName:#"DebugAssertionException"
reason:reason
userInfo:nil];
}
#catch (NSException * e)
{
NSLog(#"%#", e);
}
}
#define MYAssert(test, fmt, ...) if (!(test)) { ThrowException([NSString stringWithFormat:#"%s !!! ASSERT !!! " fmt, __PRETTY_FUNCTION__, ##__VA_ARGS__]); }
Now, You can use it like NSAssert, but instead of killing your app, you merely trigger a breakpoint:
MYAssert(bEverythingOkay, #"Something went wrong!");
// Or with arguments of course
MYAssert(bEverythingOkay, #"Something went wrong (TestValue=%zd; Reason=%#)", myTestValue, [this getLastError]);
I'm by no means an expert in this field but I use code that can break into the debugger via keyboard input.
DCIntrospect by domesticcatsoftware on github does this.
Take a look at the top of it's main file DCIntrospect.m and see how it does it.
It references a few sources, but from my experience it's quite up to date with the current assembly required to break into the debugger on armv6/7 and the simulator
External references for more background info
http://blog.timac.org/?p=190
http://developer.apple.com/library/mac/#qa/qa1361/_index.html
http://cocoawithlove.com/2008/03/break-into-debugger.html
Not sure why nobody else gave a clear straightforward answer... It's been five years but better late than never..
Preprocessor:
#ifdef DEBUG
#define manualBreakpoint() \
NSLog(#"\n\n\
Breakpoint called on: \n\n\
File: %s \n\n\
Line number: %i", __FILE__, __LINE__);\
\
raise(SIGSTOP)
#else
#define manualBreakpoint() ;
#endif
Usage:
To use it simply just type the following: manualBreakpoint();
Notes:
This will halt the app when that code is called and display the current method in your stack trace (as well as logging the file name and line number your app has halted on) IFF you are in debug mode, if you are in production mode for appstore (aka release, distribution, or archive) it will do nothing.
Using Rob's comments, and some ideas from "ios5 Programming: Pushing the Limits", and the Lumberjack framework, here's a macro to get the debugger to stop and allow for continuation during an assertion in DEBUG build, but to otherwise do as it always does during RELEASE (or actually any non-DEBUG) build.
#ifdef DEBUG
#define MyAssert(condition, desc, ...) \
if (!(condition)) { \
NSLog((desc), ## __VA_ARGS__); \
if (AmIBeingDebugged()) \
kill (getpid(), SIGSTOP); \
else { \
NSLog(#"%#, %d: could not break into debugger.", THIS_FILE, __LINE__); \
} \
}
#define MyCAssert(condition, desc, ...) \
if (!(condition)) { \
NSLog((desc), ## __VA_ARGS__); \
if (AmIBeingDebugged()) \
kill (getpid(), SIGSTOP); \
else \
NSLog(#"%#, %d: could not break into debugger.", THIS_FILE, __LINE__)); \
} \
}
#else //NOT in DEBUG
#define MyAssert(condition, desc, ...) \
if (!(condition)) { \
DDLogError((desc), ## __VA_ARGS__); \ //use NSLog if not using Lumberjack
NSAssert((condition), (desc), ## __VA_ARGS__); \
}
#define MyCAssert(condition, desc, ...) \
if (!(condition)) { \
DDLogError((desc), ## __VA_ARGS__); \ //use NSLog if not using Lumberjack
NSCAssert((condition), (desc), ## __VA_ARGS__); \
}
#endif //end DEBUG
#endif
These macros require the function AmIBeingDebugged(), which you can get from Apple at the link Rob gave: Technical Q&A QA1631: Detecting the Debugger. (You will also need to define DEBUG in your build settings.)
Note that I've chosen Lumberjack's DDLogError() over NSLog() in non-DEBUG builds because it will spit out the method, file and line number where the fatal assertion occurred.
A simple trick, if you want to use the console, is:
if (!condition_which_should_evaluate_true) {
; // Put breakpoint here
}
Then you put your breakpoint inside that line. If the condition evaluates to NO, then your breakpoint is invoked.
I am trying to write some code that interacts with an USB device in Objective C, and I got stuck on setting the callback function for incoming reports. In my case it's an IOKIT function but I think the problem is more general as I (apparently) don't know how to correctly set a C callback function in Objective-C. I've got a Class "USBController" that handles the io functions
USBController.m:
#include <CoreFoundation/CoreFoundation.h>
#include <Carbon/Carbon.h>
#include <IOKit/hid/IOHIDLib.h>
#import "USBController.h"
static void Handle_IOHIDDeviceIOHIDReportCallback(
void * inContext, // context from IOHIDDeviceRegisterInputReportCallback
IOReturn inResult, // completion result for the input report operation
void * inSender, // IOHIDDeviceRef of the device this report is from
IOHIDReportType inType, // the report type
uint32_t inReportID, // the report ID
uint8_t * inReport, // pointer to the report data
CFIndex InReportLength) // the actual size of the input report
{
printf("hello"); //just to see if the function is called
}
#implementation USBController
- (void)ConnectToDevice {
...
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
...
}
...
#end
All the functions are also declared in the header file.
I think I did pretty much the same as what I've found here, but it doesn't work. The project compiles nicely and everything works up till the moment there is input and the callback function is to be called. Then I get an "EXC_BAD_ACCESS" error. The first three arguments of the function are correct. I'm not so sure about the context..
What did I do wrong?
I am not sure at all that your EXEC_BAD_ACCESS depends on your callback. Indeed, if you say that it is called (I suppose you see the log) and since it only logs a message, there should be no problem with this.
EXEC_BAD_ACCESS is caused by an attempt to access an already deallocated object. You can get more information in two ways:
execute the program in debug mode, so when it crashes you will be able to see the stack content;
activate NSZombies or run the program using the performance tool Zombies; this will tell you exactly which object was accessed after its deallocation.
I know how to fix this. When calling this:
IOHIDDeviceRegisterInputReportCallback(tIOHIDDeviceRefs[0], report, reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,(void*)self);
You don't include the code for the creation/type of the value called report. However the method name "Handle_IOHIDDeviceIOHIDReportCallback" comes from an Apple document where there is an error in the creation of the report value. https://developer.apple.com/library/archive/technotes/tn2187/_index.html
CFIndex reportSize = 64;
uint8_t report = malloc( reportSize ); // <---- WRONG
IOHIDDeviceRegisterInputReportCallback( deviceRef,
report,
reportSize,
Handle_IOHIDDeviceIOHIDReportCallback,
context );
Instead do this:
uint8_t *report = (uint8_t *)malloc(reportSize);