How does GDB pause an execution
As you may know, we can use GDB and set breakpoints on our code to pause execution for debugging.
My questions is, how does GDB pause a process and let you view the content of registers using i r
for example. Aren't those register being used by other OS processes constantly? how do they not get overwritten?
Is it only a snapshot of the content and not live data?
c++
New contributor
add a comment |
As you may know, we can use GDB and set breakpoints on our code to pause execution for debugging.
My questions is, how does GDB pause a process and let you view the content of registers using i r
for example. Aren't those register being used by other OS processes constantly? how do they not get overwritten?
Is it only a snapshot of the content and not live data?
c++
New contributor
add a comment |
As you may know, we can use GDB and set breakpoints on our code to pause execution for debugging.
My questions is, how does GDB pause a process and let you view the content of registers using i r
for example. Aren't those register being used by other OS processes constantly? how do they not get overwritten?
Is it only a snapshot of the content and not live data?
c++
New contributor
As you may know, we can use GDB and set breakpoints on our code to pause execution for debugging.
My questions is, how does GDB pause a process and let you view the content of registers using i r
for example. Aren't those register being used by other OS processes constantly? how do they not get overwritten?
Is it only a snapshot of the content and not live data?
c++
c++
New contributor
New contributor
New contributor
asked 3 hours ago
JoeJoe
161
161
New contributor
New contributor
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
It varies slightly with the architecture, but the important points apply nearly universally:
Interrupt servicing causes the CPU state (including registers) to be saved to memory before running the ISR, and restored as the ISR exits.
If an interrupt service routine swaps the content of the memory location where those registers are saved, it can perform a context switch. Every thread has a memory region where its registers are saved when the thread isn't running.
The context switch is controlled by a thread scheduler which takes into account whether a thread is waiting for I/O, synchronization, what its priority is, signal delivery, etc. Often there's a suspend count which is factored in.
The debugger can increment the suspend count, which guarantees the thread isn't runnable. Then it can inspect (and change) the thread's saved copy of registers.
add a comment |
In addition to the great information by @BenVoigt, allow me to make some additions:
A breakpoint is set by the debugger by replacing a machine code value (an instruction or part of an instruction) in the process being debugged with a particular trap instruction at the location in code that corresponds to the desired (source) line to break at. This particular trap instruction is meant for use as a breakpoint — the debugger knows this and so does the operating system.
When the process/thread being debugged hits the trap instruction, that triggers the process @Ben is describing, which includes the half of a context swap that suspends the currently running thread (which includes saving its CPU state to memory) for potential later resumption. Since this trap is a breakpoint trap, the operating system keeps the process being debugged suspended using perhaps a mechanism @Ben describes, and notifies and eventually resumes the debugger.
The debugger uses system calls, then, to access the saved state of the suspended process/thread being debugged.
To execute (resume) the line of code that broke (which now has the particular trap instruction), the debugger will restore the original machine code value it overwrote with the breakpoint trap instruction, possibly set another trap somewhere else (e.g. if single stepping, or the user makes new breakpoints), and mark the process/thread as runnable, perhaps using a mechanism as @Ben describes.
Actual details can be more complicated, in that keeping a long running breakpoint that is hit means doing something like swapping out the breakpoint trap for real code so that line can run, and then swapping the breakpoint back in again...
Aren't those register being used by other OS processes constantly? how do they not get overwritten?
As @Ben describes, using the already existing thread suspend/resume feature (the context switching/swapping of multitasking) that allows processors to be shared by multiple processes/threads using time slicing.
Is it only a snapshot of the content and not live data?
It is both. Since the thread that hit the breakpoint is suspended, it a snapshot of the live data. If you alter the CPU registers and resume the process, the debugger will alter the suspended register context using system calls — this suspended context lives in an operating system data structure for the thread — and when the process/thread being debugged resumes, it will restore the altered values.
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "131"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Joe is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f386175%2fhow-does-gdb-pause-an-execution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
It varies slightly with the architecture, but the important points apply nearly universally:
Interrupt servicing causes the CPU state (including registers) to be saved to memory before running the ISR, and restored as the ISR exits.
If an interrupt service routine swaps the content of the memory location where those registers are saved, it can perform a context switch. Every thread has a memory region where its registers are saved when the thread isn't running.
The context switch is controlled by a thread scheduler which takes into account whether a thread is waiting for I/O, synchronization, what its priority is, signal delivery, etc. Often there's a suspend count which is factored in.
The debugger can increment the suspend count, which guarantees the thread isn't runnable. Then it can inspect (and change) the thread's saved copy of registers.
add a comment |
It varies slightly with the architecture, but the important points apply nearly universally:
Interrupt servicing causes the CPU state (including registers) to be saved to memory before running the ISR, and restored as the ISR exits.
If an interrupt service routine swaps the content of the memory location where those registers are saved, it can perform a context switch. Every thread has a memory region where its registers are saved when the thread isn't running.
The context switch is controlled by a thread scheduler which takes into account whether a thread is waiting for I/O, synchronization, what its priority is, signal delivery, etc. Often there's a suspend count which is factored in.
The debugger can increment the suspend count, which guarantees the thread isn't runnable. Then it can inspect (and change) the thread's saved copy of registers.
add a comment |
It varies slightly with the architecture, but the important points apply nearly universally:
Interrupt servicing causes the CPU state (including registers) to be saved to memory before running the ISR, and restored as the ISR exits.
If an interrupt service routine swaps the content of the memory location where those registers are saved, it can perform a context switch. Every thread has a memory region where its registers are saved when the thread isn't running.
The context switch is controlled by a thread scheduler which takes into account whether a thread is waiting for I/O, synchronization, what its priority is, signal delivery, etc. Often there's a suspend count which is factored in.
The debugger can increment the suspend count, which guarantees the thread isn't runnable. Then it can inspect (and change) the thread's saved copy of registers.
It varies slightly with the architecture, but the important points apply nearly universally:
Interrupt servicing causes the CPU state (including registers) to be saved to memory before running the ISR, and restored as the ISR exits.
If an interrupt service routine swaps the content of the memory location where those registers are saved, it can perform a context switch. Every thread has a memory region where its registers are saved when the thread isn't running.
The context switch is controlled by a thread scheduler which takes into account whether a thread is waiting for I/O, synchronization, what its priority is, signal delivery, etc. Often there's a suspend count which is factored in.
The debugger can increment the suspend count, which guarantees the thread isn't runnable. Then it can inspect (and change) the thread's saved copy of registers.
answered 3 hours ago
Ben VoigtBen Voigt
2,8251622
2,8251622
add a comment |
add a comment |
In addition to the great information by @BenVoigt, allow me to make some additions:
A breakpoint is set by the debugger by replacing a machine code value (an instruction or part of an instruction) in the process being debugged with a particular trap instruction at the location in code that corresponds to the desired (source) line to break at. This particular trap instruction is meant for use as a breakpoint — the debugger knows this and so does the operating system.
When the process/thread being debugged hits the trap instruction, that triggers the process @Ben is describing, which includes the half of a context swap that suspends the currently running thread (which includes saving its CPU state to memory) for potential later resumption. Since this trap is a breakpoint trap, the operating system keeps the process being debugged suspended using perhaps a mechanism @Ben describes, and notifies and eventually resumes the debugger.
The debugger uses system calls, then, to access the saved state of the suspended process/thread being debugged.
To execute (resume) the line of code that broke (which now has the particular trap instruction), the debugger will restore the original machine code value it overwrote with the breakpoint trap instruction, possibly set another trap somewhere else (e.g. if single stepping, or the user makes new breakpoints), and mark the process/thread as runnable, perhaps using a mechanism as @Ben describes.
Actual details can be more complicated, in that keeping a long running breakpoint that is hit means doing something like swapping out the breakpoint trap for real code so that line can run, and then swapping the breakpoint back in again...
Aren't those register being used by other OS processes constantly? how do they not get overwritten?
As @Ben describes, using the already existing thread suspend/resume feature (the context switching/swapping of multitasking) that allows processors to be shared by multiple processes/threads using time slicing.
Is it only a snapshot of the content and not live data?
It is both. Since the thread that hit the breakpoint is suspended, it a snapshot of the live data. If you alter the CPU registers and resume the process, the debugger will alter the suspended register context using system calls — this suspended context lives in an operating system data structure for the thread — and when the process/thread being debugged resumes, it will restore the altered values.
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
add a comment |
In addition to the great information by @BenVoigt, allow me to make some additions:
A breakpoint is set by the debugger by replacing a machine code value (an instruction or part of an instruction) in the process being debugged with a particular trap instruction at the location in code that corresponds to the desired (source) line to break at. This particular trap instruction is meant for use as a breakpoint — the debugger knows this and so does the operating system.
When the process/thread being debugged hits the trap instruction, that triggers the process @Ben is describing, which includes the half of a context swap that suspends the currently running thread (which includes saving its CPU state to memory) for potential later resumption. Since this trap is a breakpoint trap, the operating system keeps the process being debugged suspended using perhaps a mechanism @Ben describes, and notifies and eventually resumes the debugger.
The debugger uses system calls, then, to access the saved state of the suspended process/thread being debugged.
To execute (resume) the line of code that broke (which now has the particular trap instruction), the debugger will restore the original machine code value it overwrote with the breakpoint trap instruction, possibly set another trap somewhere else (e.g. if single stepping, or the user makes new breakpoints), and mark the process/thread as runnable, perhaps using a mechanism as @Ben describes.
Actual details can be more complicated, in that keeping a long running breakpoint that is hit means doing something like swapping out the breakpoint trap for real code so that line can run, and then swapping the breakpoint back in again...
Aren't those register being used by other OS processes constantly? how do they not get overwritten?
As @Ben describes, using the already existing thread suspend/resume feature (the context switching/swapping of multitasking) that allows processors to be shared by multiple processes/threads using time slicing.
Is it only a snapshot of the content and not live data?
It is both. Since the thread that hit the breakpoint is suspended, it a snapshot of the live data. If you alter the CPU registers and resume the process, the debugger will alter the suspended register context using system calls — this suspended context lives in an operating system data structure for the thread — and when the process/thread being debugged resumes, it will restore the altered values.
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
add a comment |
In addition to the great information by @BenVoigt, allow me to make some additions:
A breakpoint is set by the debugger by replacing a machine code value (an instruction or part of an instruction) in the process being debugged with a particular trap instruction at the location in code that corresponds to the desired (source) line to break at. This particular trap instruction is meant for use as a breakpoint — the debugger knows this and so does the operating system.
When the process/thread being debugged hits the trap instruction, that triggers the process @Ben is describing, which includes the half of a context swap that suspends the currently running thread (which includes saving its CPU state to memory) for potential later resumption. Since this trap is a breakpoint trap, the operating system keeps the process being debugged suspended using perhaps a mechanism @Ben describes, and notifies and eventually resumes the debugger.
The debugger uses system calls, then, to access the saved state of the suspended process/thread being debugged.
To execute (resume) the line of code that broke (which now has the particular trap instruction), the debugger will restore the original machine code value it overwrote with the breakpoint trap instruction, possibly set another trap somewhere else (e.g. if single stepping, or the user makes new breakpoints), and mark the process/thread as runnable, perhaps using a mechanism as @Ben describes.
Actual details can be more complicated, in that keeping a long running breakpoint that is hit means doing something like swapping out the breakpoint trap for real code so that line can run, and then swapping the breakpoint back in again...
Aren't those register being used by other OS processes constantly? how do they not get overwritten?
As @Ben describes, using the already existing thread suspend/resume feature (the context switching/swapping of multitasking) that allows processors to be shared by multiple processes/threads using time slicing.
Is it only a snapshot of the content and not live data?
It is both. Since the thread that hit the breakpoint is suspended, it a snapshot of the live data. If you alter the CPU registers and resume the process, the debugger will alter the suspended register context using system calls — this suspended context lives in an operating system data structure for the thread — and when the process/thread being debugged resumes, it will restore the altered values.
In addition to the great information by @BenVoigt, allow me to make some additions:
A breakpoint is set by the debugger by replacing a machine code value (an instruction or part of an instruction) in the process being debugged with a particular trap instruction at the location in code that corresponds to the desired (source) line to break at. This particular trap instruction is meant for use as a breakpoint — the debugger knows this and so does the operating system.
When the process/thread being debugged hits the trap instruction, that triggers the process @Ben is describing, which includes the half of a context swap that suspends the currently running thread (which includes saving its CPU state to memory) for potential later resumption. Since this trap is a breakpoint trap, the operating system keeps the process being debugged suspended using perhaps a mechanism @Ben describes, and notifies and eventually resumes the debugger.
The debugger uses system calls, then, to access the saved state of the suspended process/thread being debugged.
To execute (resume) the line of code that broke (which now has the particular trap instruction), the debugger will restore the original machine code value it overwrote with the breakpoint trap instruction, possibly set another trap somewhere else (e.g. if single stepping, or the user makes new breakpoints), and mark the process/thread as runnable, perhaps using a mechanism as @Ben describes.
Actual details can be more complicated, in that keeping a long running breakpoint that is hit means doing something like swapping out the breakpoint trap for real code so that line can run, and then swapping the breakpoint back in again...
Aren't those register being used by other OS processes constantly? how do they not get overwritten?
As @Ben describes, using the already existing thread suspend/resume feature (the context switching/swapping of multitasking) that allows processors to be shared by multiple processes/threads using time slicing.
Is it only a snapshot of the content and not live data?
It is both. Since the thread that hit the breakpoint is suspended, it a snapshot of the live data. If you alter the CPU registers and resume the process, the debugger will alter the suspended register context using system calls — this suspended context lives in an operating system data structure for the thread — and when the process/thread being debugged resumes, it will restore the altered values.
edited 1 hour ago
answered 1 hour ago
Erik EidtErik Eidt
23k43160
23k43160
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
add a comment |
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
Well, most processor architectures support debug traps that for example trigger when the IP (instruction pointer) is equal to the address stored in a breakpoint register, saving the need to rewrite code. (By matching registers other than IP, you can get data breakpoints, and by trapping after every instruction, you can get single stepping) What you described is also possible of course, as long as the code isn't in a readonly memory.
– Ben Voigt
1 hour ago
add a comment |
Joe is a new contributor. Be nice, and check out our Code of Conduct.
Joe is a new contributor. Be nice, and check out our Code of Conduct.
Joe is a new contributor. Be nice, and check out our Code of Conduct.
Joe is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Software Engineering Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fsoftwareengineering.stackexchange.com%2fquestions%2f386175%2fhow-does-gdb-pause-an-execution%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
var $window = $(window),
onScroll = function(e) {
var $elem = $('.new-login-left'),
docViewTop = $window.scrollTop(),
docViewBottom = docViewTop + $window.height(),
elemTop = $elem.offset().top,
elemBottom = elemTop + $elem.height();
if ((docViewTop elemBottom)) {
StackExchange.using('gps', function() { StackExchange.gps.track('embedded_signup_form.view', { location: 'question_page' }); });
$window.unbind('scroll', onScroll);
}
};
$window.on('scroll', onScroll);
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown