How to know which code caused a trap in xv6 when debugging? - operating-system

Here is what I suppose: When the code causes a trap (system call or exceptions), xv6 will replace the registers with certain values to transfer the control to alltraps(), in which trap() is called.
But sometimes xv6 runs into trap() out of my expectation, and I want to know why it got into this trap. When debugging, after I set a break point in trap() and xv6 stopped here, I can only see this in the debugger (I'm using CLion). In the call stack, the bottom stack frame is alltraps() so I can't find out when and why the trap is caused.
I want to find out in which file, at which line the trap is caused for a certain call of trap(). Is this possible?

If you will examine trap() code more carefully, you will see that it also handles hardware interrupts (timer, ide and so on).
36 void
37 trap(struct trapframe *tf)
38 {
39 if(tf->trapno == T_SYSCALL){
...
47 }
48
49 switch(tf->trapno){
50 case T_IRQ0 + IRQ_TIMER:
51 if(cpuid() == 0){
52 acquire(&tickslock);
53 ticks++;
54 wakeup(&ticks);
55 release(&tickslock);
56 }
57 lapiceoi();
58 break;
59 case T_IRQ0 + IRQ_IDE:
...
So what are you seeing is hardware interrupt coming and processor transfers control to one of the IDT vectors then to alltraps then to trap(). Most likely you are facing timer interrupt, which is used for context switch.
I want to find out in which file, at which line the trap is caused for a certain call of trap(). Is this possible?
No it is not possible, because this is a hardware event and it has no relation to source code.

Related

Finding the cause of EXC_BAD_ACCESS Code=1 on startup of Swift iOS App

I'm writing a Swift iOS app in XCode 12.5 that lets you take notes on "events" (interactions) with your contacts. After making some changes, launching the app on my phone yielded an EXC_BAD_ACCESS error from a part of the app I haven't touched in months - a notification manager that creates a reminder based on the latest notes you've taken on any of your contacts.
As background, I use CoreData to store the app's data on contacts and notes, using NSManagedObjects to represent Contact objects; each Contact object has 0 to many Event objects. The app was working fine on my iPhone as of a few months ago, and on the simulator as I've been making changes to the code in recent days/weeks. I've tried using the Instruments tool to check for Zombies and Leaks and have come up empty-handed. I've also tried to assess variables on the line of code causing the bad access error and can't find issues.
At a high level, this is the execution sequence leading to the problem:
App loads object context from Core Data
Notification Manager checks if app is authorized for notification
If so, the closure calls a method to add a reminder
within addReminder(), it calls getEvents(...) (see below)
getEvents raises the EXC_BAD_ACCESS error when cycling through each Contact and trying to access the "events" for each contact (an NSManagedObject). I tried to make changes to isolate any issues associated with the contact or events, but these variables seem to be filled with reasonable data (e.g., the contact may have a proper name or the contact's events list may be empty)
func getEvents(last90days: Bool = false) -> [Event] {
var events = [Event]()
let keyDate = Date(timeIntervalSinceNow: -90 * 60 * 60 * 24)
for case let event as Event in (self.events ?? []) { // this is the line where the EXC_BAD_ACCESS occurs. Even if I nil-coalesce above this line separately, the problem still persists.
if last90days && event.timestamp != nil {
if event.timestamp == nil {
continue
}
if event.timestamp! < keyDate {
continue
}
}
events.append(event)
}
return events
}
_Error Message:_Thread 4: EXC_BAD_ACCESS (code=1, address=0x1fa9bf0)
Stack Trace:
* thread #4, queue = 'com.apple.usernotifications.UNUserNotificationServiceConnection.call-out', stop reason = EXC_BAD_ACCESS (code=1, address=0x1fa9bf0)
frame #0: 0x00000001ace04334 libobjc.A.dylib`object_getMethodImplementation + 48
frame #1: 0x00000001982d7c04 CoreFoundation`_NSIsNSSet + 40
frame #2: 0x00000001981aaf18 CoreFoundation`-[NSMutableSet unionSet:] + 108
frame #3: 0x000000019e3c93b0 CoreData`-[_NSFaultingMutableSet willReadWithContents:] + 636
frame #4: 0x000000019e3e7ff4 CoreData`-[_NSFaultingMutableSet countByEnumeratingWithState:objects:count:] + 48
frame #5: 0x000000019bd12bd0 libswiftFoundation.dylib`Foundation.NSFastEnumerationIterator.next() -> Swift.Optional<Any> + 180
* frame #6: 0x0000000100dbb03c myApp`Contact.getEvents(last90days=false, self=0x0000000281b32f80) at Contact+helpers.swift:48:9
frame #7: 0x0000000100db7bc8 myApp`InteractionAnalyzer.countInteractions(startDate=2022-01-03 04:12:17 UTC, endDate=2022-01-10 04:12:17 UTC, name=nil, onlyIncludeNewSparks=false, excludeNewSparks=false, sparkStartDate=nil, self=0x00000002838feb20) at InteractionAnalyzer.swift:24:48
frame #8: 0x0000000100dfac18 myApp`NotificationManager.getNotificationString(self=0x000000028377a220) at NotificationManager.swift:74:60
frame #9: 0x0000000100dfa368 myApp`NotificationManager.addNotificationRequest(self=0x000000028377a220) at NotificationManager.swift:62:29
frame #10: 0x0000000100df9ab8 myApp`closure #1 in NotificationManager.addReminder(settings=0x0000000281355490, self=0x000000028377a220) at NotificationManager.swift:36:22
frame #11: 0x0000000100df98d4 myApp`thunk for #escaping #callee_guaranteed (#guaranteed UNNotificationSettings) -> () at <compiler-generated>:0
frame #12: 0x000000010146c0b4 libdispatch.dylib`_dispatch_call_block_and_release + 32
frame #13: 0x000000010146dde0 libdispatch.dylib`_dispatch_client_callout + 20
frame #14: 0x0000000101475ef0 libdispatch.dylib`_dispatch_lane_serial_drain + 788
frame #15: 0x0000000101476d48 libdispatch.dylib`_dispatch_lane_invoke + 496
frame #16: 0x0000000101483a50 libdispatch.dylib`_dispatch_workloop_worker_thread + 1600
frame #17: 0x00000001e3f927a4 libsystem_pthread.dylib`_pthread_wqthread + 276
How can I get to the bottom of this cause? I've been crawling many threads on EXC_BAD_ACCESS to no avail and am hoping I'm just missing something dead simple..
Add adress sanitizer to your scheme, and run application on simulator. Hopofully sanitizer will show you more precisely where in your code you have data race.
Click on your scheme (next to simulator) -> Edit scheme
Select diagnostics and check "address sanitizer"
run your application on simulator
The NSFaultingMutableSet in the stack trace pointed to an issue with accessing data from my Core Data store (e.g., Event objects like self.events). My notification manager was operating on a separate thread and creating an unstable situation where Core Data (which I hadn't set up properly for multi-thread access) was being read and modified on the main and secondary threads simultaneously.
I was able to resolve the problem by wrapping the Notification Manager code that accesses Core Data objects in a DispatchQueue.main.async {...} block. There are other ways to set up Core Data objects for access from multiple threads (e.g., Coredata - Multithreading best way), but this was the simplest solution given multi-thread access isn't a priority for what I'm trying to do.

How to generate 0xE8 (call) opcode with C++

Basically, what I have is a game which has a function MyFunc(), and it's called on 4 places in the game. One of the addresses is 0x10002000, and the bytes are E8 0B 83 01 00.
I'm injecting a DLL, and want to patch that 0xE8 (call) to my own address. When I do it with Cheat Engine's Auto Assembler and write call MYADDRESS, it generates the proper opcode, and proper bytes.
However, if I do it with the DLL, this is what I get:
What I want to achieve is call 74C611CC. So I need to generate the bytes for the opcode to be like I want instead of what is it currently (in the screenshot)
I use this kind of code:
*(BYTE*) dwPatchAddr = 0xE8;
*(DWORD*) (dwPatchAddr + 1) = (DWORD) myFunc;
An e8 instruction is a relative call instruction, not absolute. So the next 4 bytes need to be the difference between the pc when processing this instruction and your target function. So what you want is:
*(BYTE *)dwPatchAddr = 0xE8;
*(DWORD *)(dwPatchAddr + 1) = (DWORD)((char *)myFunc - (char *)(dwPatchAddr + 5));
Note that the PC address used to compute the offset is actually the address of the next instruction after the call (what will also be pushed as the return address).

gem5 cache statistics - reset and dump

I am trying to get familiar with gem5 simulator.
To start, I wrote a simple program with
int main()
{
m5_reset_stats(0, 0);
m5_dump_stats(0, 0);
return 0;
}
I compiled it with util/m5/m5op_x86.S and ran it using...
./build/X86/gem5.opt configs/example/se.py --caches -c ~/tmp/hello
The m5out/stats.txt shows (among other things)...
system.cpu.dcache.ReadReq_hits::total 881
system.cpu.dcache.WriteReq_hits::total 917
system.cpu.dcache.ReadReq_misses::total 54
system.cpu.dcache.WriteReq_misses::total 42
Why is an empty function showing so much hits and misses? Are the hits and misses caused by libc? If so, then what is the purpose of m5_reset_stats() and m5_dump_stats()?
I would check in the stats.txt file if there are two chunks of
---Begin---
---End-----
because as you explained it, the simulator is supposed to dump the stats at dump_stats(0,0) and at the end of the run. So, it seems like you either are looking at one of those intervals (and I would expect the other interval to have 0 for all stats); or there was a bug in the simulation and the dump_stats() (or reset_stats())didn't actually do anything. That actually happened to me plenty of times, but I am not really sure as to the source of this bug.
If you want to troubleshoot further, you could do the following:
Look at the disassembly of your code and find the reset_stats.w and dump_stats.w
Dump a trace from gem5 and see if it ends up executing the dump and reset instructions and also what instructions (and how many) are executed before/after.
Hope this helps!

What can cause this SIGSEGV error?

I received a crash log that I cannot explain. I have searched around and it appears that the SIGSEGV has something to do with memory. But in my case there is nothing of my own code except for the main.m in the stacktrace. Also it doesn't seem to symbolicate any of the system libraries.
The crash so far only happened on one iPhone. On other phones I haven't been able to reproduce it. Right now I'm completely stuck and don't know where to continue so if anyone has seen something like this before it would be good to hear their problem and resolution.
The crash log:
Incident Identifier: TODO
CrashReporter Key: TODO
Hardware Model: iPhone4,1
OS Version: iPhone OS 6.1.3 (10B329)
Report Version: 104
Exception Type: SIGSEGV
Exception Codes: SEGV_ACCERR at 0x41fd5903
Crashed Thread: 0
Thread 0 Crashed:
0 libobjc.A.dylib 0x3b0b9564 0x3b0b6000 + 13668
1 libobjc.A.dylib 0x3b0bb1d7 0x3b0b6000 + 20951
2 CoreFoundation 0x33396605 0x332d4000 + 796165
3 CoreFoundation 0x3339635d 0x332d4000 + 795485
4 libobjc.A.dylib 0x3b0bea65 0x3b0b6000 + 35429
5 libc++abi.dylib 0x3ab0b07b 0x3ab0a000 + 4219
6 libc++abi.dylib 0x3ab0b114 0x3ab0a000 + 4372
7 libc++abi.dylib 0x3ab0c599 0x3ab0a000 + 9625
8 libobjc.A.dylib 0x3b0be9d1 0x3b0b6000 + 35281
9 CoreFoundation 0x332dcf21 0x332d4000 + 36641
10 CoreFoundation 0x332dcd49 0x332d4000 + 36169
11 GraphicsServices 0x36eb52eb 0x36eb0000 + 21227
12 UIKit 0x351f2301 0x3519b000 + 357121
13 Stylbar 0x0007109f main (main.m:21)
Edit 3th of May:
The crash log is sent by a user. I haven't been able to reproduce the issue myself unfortunately, which is why it's so difficult for me to figure out what went wrong with just this crash log.
It appeared to have happened about 15 times in a row for the same user when opening a certain view controller. The view controller does several calls to a server to load a post, comments and images and profile pictures. All the code that's executed when this view controller is opened is probably over 2000 lines of code (excluding the RestKit and SBWebImage libraries that are used within this code). Posting that code here wouldn't help anyone I'm afraid.
The most simple and useful way to spend your time hunting for the cause of the crash is to look at your code and focus on places where UIKit has a delegate that points back into your code. For example, I found that the most common place this sort of thing would show up was in UITableView. The reason these problems are so hard to track down is that they might only happen in a low memory situation or in some uncommon UI condition that is very hard to reproduce. It is better to just do a code review and make sure that delegate that are set to point to your classes are set back to nil in your own object destructors. If you have many developers, it is often better to work on some higher level abstractions like a generic table and cell class that is used throughout the project than to have every developer coding up a UITableView and making mistakes like forgetting to nil out the delegate that are very difficult to find.
SIGSEGV is a problem the occurs when your application tries to access an address of memory that doesn't exists or some address where is already reserved to another program. I have the same issue with an application right now but I have to review my code to figure it out better. One clue for this kind of problem could be something equivalent to this (found in wikipedia):
#include <stdlib.h>
int main(void)
{
char p = NULL; / p is a pointer to char that initializes poiting to "nowhere"*/
* p = 'x'; /* Tries to save the char 'x' in 'no address'*/
return 0;
}
I hope this can help someone.

How to read objective-c stack traces

i have the following stack trace:
0 MyApp 0x000833a3 +[TFCrashHandler backtrace] + 26
1 MyApp 0x000836bd TFSignalHandler + 28
2 libsystem_c.dylib 0x33eac727 _sigtramp + 34
3 ??? 0x00000002 0x0 + 2
4 MyApp 0x000803f1 msgpack_unpack_next + 112
5 MyApp 0x0007faeb +[MessagePackParser parseData:] + 74
6 MyApp 0x0007f84b -[NSData(NSData_MessagePack) messagePackParse] + 26
7 MyApp 0x000254c3 +[Http get:params:cacheMins:msgPack:complete:] + 146
...
And i'm wondering how to read it:
I assume i go from the bottom up, eg line 7 called line 6 called line 5, etc.
What does the '+ 112' on line 4 mean? Is that a line number in the code file where it crashed?
What does the '???' on line 3 mean?
Thanks a lot
0 MyApp 0x000833a3 +[TFCrashHandler backtrace] + 26
Crash was generated from +[TFCrashHandler backtrace] + 26; from whatever instruction fell at that symbol location + 26 bytes.
If that is really the bottom of your stack trace and it crashed there, then the TCrashHandler is obscuring the real crash. The real crash looks to be a couple of frames above.
1 MyApp 0x000836bd TFSignalHandler + 28
TFSignalHandler was what called +backtrace.
2 libsystem_c.dylib 0x33eac727 _sigtramp + 34
Ewww... a signal trampoline. The app received a signal and the a trampoline was set to call TFSignalHandler().
There are situations where a signal handler might be called on a random thread. I.e. there is a minuscule chance that this particular crash had nothing to do with the parser and everything to do with a crash somewhere else. However, without knowing more about the parser, I'd question whether it is hardened against malicious input (which could certainly cause a crash like this).
3 ??? 0x00000002 0x0 + 2
Stack was undecodable. Ignore. Meaningless. Best case; fallout from compiler optimization. Worst case; somebody pooped on the stack and the backtrace mechanism can't figure out what is going on (highly unlikely -- usually, stack poop splatters to the point of preventing a full backtrace).
4 MyApp 0x000803f1 msgpack_unpack_next + 112
Ooooh... trickzy. Someone is using C to parse stuff. And it crashed. Whatever instruction was 112 bytes from the entry point to the function went boom. But, not really, because it called the signal handler and was handled by that; which is still a boom but the signal handler has effectively destroyed additional forensic evidence.
The "trickzy" comment references that an optimizing compiler against a big pile o' C can end up collapsing frames to the point that the crash could have happened in a function well below this one.
5 MyApp 0x0007faeb +[MessagePackParser parseData:] + 74
MessagePackParser was parsing when things went horribly wrong.
6 MyApp 0x0007f84b -[NSData(NSData_MessagePack) messagePackParse] + 26
7 MyApp 0x000254c3 +[Http get:params:cacheMins:msgPack:complete:] + 146
Ahh... yes.... somebody done grabbed some data from HTTP and it was malformed, causing the crash.
Bottom line; the parser got bogus input and crashed. There was a signal handler in place that tried to help by creating a backtrace, but -- apparently -- didn't really reveal any more info. A long shot alternative is that the signal was generated somewhere else and this thread was randomly selected to handle it -- if you can consistently recreate this crash, the random-thread-signal case is unlikely.
Unless you have a capture of the input data or can somehow guess how msgpack_unpack_next() might crash, you are out of luck without providing more info.
The '???' is something that can't be identified, probably code that was compiled without symbols, but could also be something else.
Those are the line numbers in the implementation file. And the hex is the pointer in memory to the line call.