microsoft / microsoft/MIEngine
entrypoint behaviour with gdb <-> gdbserver
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 859
- Forks
- 233
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 3
Description
I am using VSCode/cpptools to debug a C program built with gcc, using a gdb <-> gdbserver connection to perform the debug.
Regarding the following code in MIEngine:
https://github.com/microsoft/MIEngine/blob/bc7dccbc0ae509b6dcd7d1e3c6b14f30bfd5064f/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs#L1102
This works fine for me when the C program is built for and run on Windows. Here the stack frame information the above MIEngine code sees is:
1: (1001) ->1016^done,stack=[frame={level="0",addr="0x00007ffe3e6d119d",func="ntdll!LdrInitShimEngineDynamic",from="target:C:\\Windows\\SYSTEM32\\ntdll.dll",arch="i386:x86-64"},frame={level="1",addr="0x00007ffe3e6d455f",func="ntdll!LdrInitShimEngineDynamic",from="target:C:\\Windows\\SYSTEM32\\ntdll.dll",arch="i386:x86-64"},frame={level="2",addr="0x00007ffe3e6c1d75",func="ntdll!memset",from="target:C:\\Windows\\SYSTEM32\\ntdll.dll",arch="i386:x86-64"},frame={level="3",addr="0x00007ffe3e6717d3",func="ntdll!LdrInitializeThunk",from="target:C:\\Windows\\SYSTEM32\\ntdll.dll",arch="i386:x86-64"},frame={level="4",addr="0x00007ffe3e67177e",func="ntdll!LdrInitializeThunk",from="target:C:\\Windows\\SYSTEM32\\ntdll.dll",arch="i386:x86-64"},frame={level="5",addr="0x0000000000000000",func="??",arch="i386:x86-64"}]
So because there is no mention of "file", it results in this code not setting this.EntrypointHit to true, which seems to work out well later on when the breakpoint set at the beginning of main() (for stopAtEntry I guess) is hit and processed.
However building the same C program for an embedded target and running on that, the stack frame information comes back as:
1: (2722) ->1014^done,stack=[frame={level="0",addr="0x00000000",func="_start",file="../riscv-sdk-picolibc/picocrt/machine/riscv/crt0.c",fullname="/jenkins/workspace/sdk_build_gnu_tools-windows/riscv-sdk-gnu-toolchain/build-picolibc/../riscv-sdk-picolibc/picocrt/machine/riscv/crt0.c",line="69",arch="riscv:rv32"}]
So does mention "file".
I believe the difference may be that in the embedded case we do have source code to the start-up function (_start() in crt0.c), whereas on the Windows case there was no source code for the ntdll functions.
The problem the above gives in the embedded case is that the presence of "file" means this.EntrypointHit is set to true. This then causes problems when the breakpoint at the beginning of main() is hit and processed, and results in it being reported as an "Unknown breakpoint" exception at the following line of code:
https://github.com/microsoft/MIEngine/blob/bc7dccbc0ae509b6dcd7d1e3c6b14f30bfd5064f/src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs#L1179
I have made a local fix to check that file does not contain "crt0.c", but it feels very temporary :-) So just wondering what a more permanent fix might be?
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in src/MIDebugEngine/Engine.Impl/DebuggedProcess.cs around lines 1102 and 1179, focusing on how stack frames set EntrypointHit and how the main() breakpoint is handled. Reproduce the gdb/gdbserver case with the embedded _start frame from crt0.c, then verify that hitting main() is handled normally rather than reported as an unknown breakpoint.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- c, csharp, vscode
- Domain
- devtools, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100