* how to make gdb happy with my linkmap @ 2008-12-18 21:42 Mathieu Lacage 2008-12-18 21:49 ` Daniel Jacobowitz 0 siblings, 1 reply; 10+ messages in thread From: Mathieu Lacage @ 2008-12-18 21:42 UTC (permalink / raw) To: gdb hi, I am currently trying to write a small ELF loader and make gdb be happy with it. One of the things I have been doing until now is manage the following link map: (gdb) info linkmap 084661e0 ldso 08430518 084661e0 /lib/libc.so.6 (gdb) The most notable thing to note here is that the first item in the linkmap is not the main binary: it is the loader itself. This, however, seems to be problematic for gdb since I get the following message: warning: Temporarily disabling breakpoints for unloaded shared library "ldso" when I invoke the _r_debug_state function where gdb has put a breakpoint (I should point out that, of course, I did not remove _any_ entry from the link map at this point) Although it seems clear to me that I won't be able to keep managing my link map as I do now and that I will have to move the main binary as the first entry in the map (I have already done this and it makes gdb much happier), I was trying to figure out why this so problematic for gdb, mainly because I fear that there are some other subtle requirements from gdb on the structure of the link map. Hence, my question: what are the requirements on the structure of a linkmap which is compatible with gdb's usage (beyond the mere ABI offset requirements). I am also curious to know if there is anywhere a document which describes the overall interface between gdb and the inferior's loader: so far, reading the code has been enough for me to figure out how this all works but, well, I wonder if I could have saved myself all this code-reading work. Anyhow, that piece of code is fairly readable and really nicely structured so, thanks a lot for this cool software I have been using for so long. Mathieu -- Mathieu Lacage <mathieu.lacage@gmail.com> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2008-12-18 21:42 how to make gdb happy with my linkmap Mathieu Lacage @ 2008-12-18 21:49 ` Daniel Jacobowitz 2008-12-18 22:03 ` Mathieu Lacage 0 siblings, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2008-12-18 21:49 UTC (permalink / raw) To: Mathieu Lacage; +Cc: gdb On Thu, Dec 18, 2008 at 10:41:20PM +0100, Mathieu Lacage wrote: > hi, > > I am currently trying to write a small ELF loader and make gdb be > happy with it. On SVR4 systems, basically, you can't. There is some information you won't be able to update because it lives in the kernel (auxilliary vector). This is one of the reasons I recently implemented "set wrapper"; if the loader is far enough along when GDB starts looking at it, and has a link map already set up, then it will (generally) not go poking around the auxilliary vector. > Hence, my question: what are the requirements on the structure of a > linkmap which is compatible with gdb's usage (beyond the mere ABI > offset requirements). I don't think this is possible to answer. The answer is that GDB is written to work as best it can with all the system loaders we've encountered. If there's a change that would make things easier for your loader, without breaking any of those systems, you're welcome to propose it :-) -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2008-12-18 21:49 ` Daniel Jacobowitz @ 2008-12-18 22:03 ` Mathieu Lacage 2008-12-18 22:10 ` Daniel Jacobowitz 0 siblings, 1 reply; 10+ messages in thread From: Mathieu Lacage @ 2008-12-18 22:03 UTC (permalink / raw) To: Mathieu Lacage, gdb On Thu, Dec 18, 2008 at 10:48 PM, Daniel Jacobowitz <drow@false.org> wrote: > On Thu, Dec 18, 2008 at 10:41:20PM +0100, Mathieu Lacage wrote: >> hi, >> >> I am currently trying to write a small ELF loader and make gdb be >> happy with it. > > On SVR4 systems, basically, you can't. There is some information you > won't be able to update because it lives in the kernel (auxilliary > vector). This is one of the reasons I recently implemented "set erm, I might be totally naive, but, how does the libc loader achieve this then ? The only thing I am trying to do is be sufficiently compatible with the libc loader to make gdb happy with my loader. Did I mention that I am trying to replace the libc loader rather than try to make two loaders co-exist in the same process image (which would create another set of challenging problems from a compatibility perspective). > wrapper"; if the loader is far enough along when GDB starts looking will grep for this. > at it, and has a link map already set up, then it will (generally) > not go poking around the auxilliary vector. > >> Hence, my question: what are the requirements on the structure of a >> linkmap which is compatible with gdb's usage (beyond the mere ABI >> offset requirements). > > I don't think this is possible to answer. The answer is that GDB is > written to work as best it can with all the system loaders we've > encountered. If there's a change that would make things easier for > your loader, without breaking any of those systems, you're welcome to > propose it :-) Ok, my question then, is: what can I do in my loader to be fully compatible with what gdb expects :) I am willing to go through quite a bit of pain in the name of compatibility: whatever gdb asks me to do will be probably orders of magnitude easier than what glibc is asking me to provide Mathieu -- Mathieu Lacage <mathieu.lacage@gmail.com> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2008-12-18 22:03 ` Mathieu Lacage @ 2008-12-18 22:10 ` Daniel Jacobowitz 2008-12-26 10:40 ` Mathieu Lacage 0 siblings, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2008-12-18 22:10 UTC (permalink / raw) To: Mathieu Lacage; +Cc: gdb On Thu, Dec 18, 2008 at 11:02:22PM +0100, Mathieu Lacage wrote: > > On SVR4 systems, basically, you can't. There is some information you > > won't be able to update because it lives in the kernel (auxilliary > > vector). This is one of the reasons I recently implemented "set > > erm, I might be totally naive, but, how does the libc loader achieve > this then ? The only thing I am trying to do is be sufficiently > compatible with the libc loader to make gdb happy with my loader. Did > I mention that I am trying to replace the libc loader rather than try > to make two loaders co-exist in the same process image (which would > create another set of challenging problems from a compatibility > perspective). Oh! Sorry. Then I was off on a tangent. The salient difference is whether your loader is started by the kernel based on a PT_INTERP entry in the executable, or from the command line. If it's started by PT_INTERP, things are much easier to handle. The only things I can think of are having the main application first, and having the debug function be named _dl_debug_state (because we set a breakpoint before _r_debug is initialized). There's not much more to it. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2008-12-18 22:10 ` Daniel Jacobowitz @ 2008-12-26 10:40 ` Mathieu Lacage 2008-12-26 12:54 ` Daniel Jacobowitz 0 siblings, 1 reply; 10+ messages in thread From: Mathieu Lacage @ 2008-12-26 10:40 UTC (permalink / raw) To: Mathieu Lacage, gdb On Thu, Dec 18, 2008 at 11:10 PM, Daniel Jacobowitz <drow@false.org> wrote: > Oh! Sorry. Then I was off on a tangent. The salient difference is > whether your loader is started by the kernel based on a PT_INTERP > entry in the executable, or from the command line. If it's started > by PT_INTERP, things are much easier to handle. > > The only things I can think of are having the main application first, > and having the debug function be named _dl_debug_state (because we set > a breakpoint before _r_debug is initialized). There's not much more > to it. Ok, it appears that this is, indeed, sufficient to get good debugging when running the executable from a PT_INTERP. However, as you mentioned above, running the executable from the command-line without an associated PT_INTERP entry seems to confuse gdb quite a bit: it seems unable to place or handle breakpoints. Is there something I could do to help alleviate this problem (I would be happy to do whatever is needed in gdb proper) ? Maybe I could go and hack the on-stack aux vectors to help gdb ? regards, Mathieu -- Mathieu Lacage <mathieu.lacage@gmail.com> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2008-12-26 10:40 ` Mathieu Lacage @ 2008-12-26 12:54 ` Daniel Jacobowitz 2009-01-05 14:58 ` Mathieu Lacage 0 siblings, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2008-12-26 12:54 UTC (permalink / raw) To: Mathieu Lacage; +Cc: gdb On Fri, Dec 26, 2008 at 11:39:59AM +0100, Mathieu Lacage wrote: > Ok, it appears that this is, indeed, sufficient to get good debugging > when running the executable from a PT_INTERP. However, as you > mentioned above, running the executable from the command-line without > an associated PT_INTERP entry seems to confuse gdb quite a bit: it > seems unable to place or handle breakpoints. Is there something I > could do to help alleviate this problem (I would be happy to do > whatever is needed in gdb proper) ? Maybe I could go and hack the > on-stack aux vectors to help gdb ? Does it work any better with ld.so? I doubt it - GDB doesn't do this well, and I don't have any clear idea on how to improve it. Sorry. There's probably a way that I haven't thought of. Modifying the on-stack auxv copy won't make a difference; GDB uses the read-only copy in the kernel (since locating the stack copy is unreliable, and it is prone to corruption). -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2008-12-26 12:54 ` Daniel Jacobowitz @ 2009-01-05 14:58 ` Mathieu Lacage 2009-01-05 17:13 ` Daniel Jacobowitz 2009-01-12 15:08 ` Mathieu Lacage 0 siblings, 2 replies; 10+ messages in thread From: Mathieu Lacage @ 2009-01-05 14:58 UTC (permalink / raw) To: gdb > Does it work any better with ld.so? I doubt it - GDB doesn't do It does not seem to work any better with ld-linux.so.2. I tried to look into this a bit more but I did not make much progress. Here is what I get: mathieu@mathieu-boulot:~/code/elf-loader$ gdb ./ldso GNU gdb 6.8-debian Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "i486-linux-gnu"... (gdb) b stage1 Breakpoint 1 at 0x944: file ldso.c, line 304. (gdb) r ./hello Starting program: /home/mathieu/code/elf-loader/ldso ./hello hello Program exited normally. (gdb) What I find weird is: 1) mathieu@mathieu-boulot:~/code/elf-loader$ readelf -s ./ldso |grep stage1 225: 00000932 135 FUNC GLOBAL HIDDEN 6 stage1 mathieu@mathieu-boulot:~/code/elf-loader$ readelf -l ./ldso Elf file type is DYN (Shared object file) Entry point 0x932 There are 6 program headers, starting at offset 52 [...] i.e., stage1 is located at offset 0x932, and not 0x944 so, I can't figure out where the 0x944 displayed by gdb is coming from. I also find it surprising that gdb is actually trying to set a breakpoint at address 0x944: this is a pie binary so, gdb should know that the address will be known only once the program is run.... To summarize, 2 questions: 1) what do I need to do to make gdb _not_ attempt to really set the breakpoint before the program is run ? 2) why is gdb using 0x944 and not 0x932 ? I am shooting a bit in the dark here, obviously. Mathieu -- Mathieu Lacage <mathieu.lacage@gmail.com> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2009-01-05 14:58 ` Mathieu Lacage @ 2009-01-05 17:13 ` Daniel Jacobowitz 2009-01-07 16:46 ` Doug Evans 2009-01-12 15:08 ` Mathieu Lacage 1 sibling, 1 reply; 10+ messages in thread From: Daniel Jacobowitz @ 2009-01-05 17:13 UTC (permalink / raw) To: Mathieu Lacage; +Cc: gdb On Mon, Jan 05, 2009 at 03:58:39PM +0100, Mathieu Lacage wrote: > What I find weird is: > 1) mathieu@mathieu-boulot:~/code/elf-loader$ readelf -s ./ldso |grep stage1 > 225: 00000932 135 FUNC GLOBAL HIDDEN 6 stage1 > mathieu@mathieu-boulot:~/code/elf-loader$ readelf -l ./ldso > > Elf file type is DYN (Shared object file) > Entry point 0x932 > There are 6 program headers, starting at offset 52 > [...] > > i.e., stage1 is located at offset 0x932, and not 0x944 so, I can't > figure out where the 0x944 displayed by gdb is coming from. That's prologue skipping; it's just walking past the frame setup. This helps GDB to display function arguments correctly. > I also > find it surprising that gdb is actually trying to set a breakpoint at > address 0x944: this is a pie binary so, gdb should know that the > address will be known only once the program is run.... This is the same problem as PIE support. Ubuntu and Fedora carry some patches to improve PIE support; I think that Jan K. was talking about merging those at some point. I haven't looked at them in years. -- Daniel Jacobowitz CodeSourcery ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2009-01-05 17:13 ` Daniel Jacobowitz @ 2009-01-07 16:46 ` Doug Evans 0 siblings, 0 replies; 10+ messages in thread From: Doug Evans @ 2009-01-07 16:46 UTC (permalink / raw) To: Mathieu Lacage, gdb On Mon, Jan 5, 2009 at 9:13 AM, Daniel Jacobowitz <drow@false.org> wrote: > On Mon, Jan 05, 2009 at 03:58:39PM +0100, Mathieu Lacage wrote: >> What I find weird is: >> 1) mathieu@mathieu-boulot:~/code/elf-loader$ readelf -s ./ldso |grep stage1 >> 225: 00000932 135 FUNC GLOBAL HIDDEN 6 stage1 >> mathieu@mathieu-boulot:~/code/elf-loader$ readelf -l ./ldso >> >> Elf file type is DYN (Shared object file) >> Entry point 0x932 >> There are 6 program headers, starting at offset 52 >> [...] >> >> i.e., stage1 is located at offset 0x932, and not 0x944 so, I can't >> figure out where the 0x944 displayed by gdb is coming from. > > That's prologue skipping; it's just walking past the frame setup. > This helps GDB to display function arguments correctly. For completeness' sake, to avoid prologue skipping one can do "b *stage1". ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: how to make gdb happy with my linkmap 2009-01-05 14:58 ` Mathieu Lacage 2009-01-05 17:13 ` Daniel Jacobowitz @ 2009-01-12 15:08 ` Mathieu Lacage 1 sibling, 0 replies; 10+ messages in thread From: Mathieu Lacage @ 2009-01-12 15:08 UTC (permalink / raw) To: gdb [-- Attachment #1: Type: text/plain, Size: 2219 bytes --] Just in case it helps anyone, since I did not really have time to investigate the gdb issues, I came up with the attached elf editor which replaces the content of PT_INTERP. Eventually, I will have to deal with gdb but, not now :) Mathieu On Mon, Jan 5, 2009 at 3:58 PM, Mathieu Lacage <mathieu.lacage@gmail.com> wrote: >> Does it work any better with ld.so? I doubt it - GDB doesn't do > > It does not seem to work any better with ld-linux.so.2. I tried to > look into this a bit more but I did not make much progress. Here is > what I get: > > mathieu@mathieu-boulot:~/code/elf-loader$ gdb ./ldso > GNU gdb 6.8-debian > Copyright (C) 2008 Free Software Foundation, Inc. > License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> > This is free software: you are free to change and redistribute it. > There is NO WARRANTY, to the extent permitted by law. Type "show copying" > and "show warranty" for details. > This GDB was configured as "i486-linux-gnu"... > (gdb) b stage1 > Breakpoint 1 at 0x944: file ldso.c, line 304. > (gdb) r ./hello > Starting program: /home/mathieu/code/elf-loader/ldso ./hello > hello > > Program exited normally. > (gdb) > > What I find weird is: > 1) mathieu@mathieu-boulot:~/code/elf-loader$ readelf -s ./ldso |grep stage1 > 225: 00000932 135 FUNC GLOBAL HIDDEN 6 stage1 > mathieu@mathieu-boulot:~/code/elf-loader$ readelf -l ./ldso > > Elf file type is DYN (Shared object file) > Entry point 0x932 > There are 6 program headers, starting at offset 52 > [...] > > i.e., stage1 is located at offset 0x932, and not 0x944 so, I can't > figure out where the 0x944 displayed by gdb is coming from. I also > find it surprising that gdb is actually trying to set a breakpoint at > address 0x944: this is a pie binary so, gdb should know that the > address will be known only once the program is run.... > > To summarize, 2 questions: > 1) what do I need to do to make gdb _not_ attempt to really set the > breakpoint before the program is run ? > > 2) why is gdb using 0x944 and not 0x932 ? > > I am shooting a bit in the dark here, obviously. > > Mathieu > -- > Mathieu Lacage <mathieu.lacage@gmail.com> > -- Mathieu Lacage <mathieu.lacage@gmail.com> [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: elfedit.c --] [-- Type: text/x-csrc; name=elfedit.c, Size: 1758 bytes --] #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <elf.h> #include <link.h> #include <unistd.h> #include <stdlib.h> #include <string.h> int main (int argc, char *argv[]) { const char *filename = argv[1]; ElfW(Ehdr) header; int fd = open (filename, O_RDWR); ssize_t bytes_read = read (fd, &header, sizeof (header)); if (bytes_read != sizeof (header)) { return -1; } ElfW(Phdr) *ph = malloc (header.e_phnum * header.e_phentsize); if (ph == 0) { return -2; } if (lseek (fd, header.e_phoff, SEEK_SET) == -1) { return -3; } if (read (fd, ph, header.e_phnum * header.e_phentsize) != header.e_phnum * header.e_phentsize) { return -4; } int i; for (i = 0; i < header.e_phnum; i++) { if (ph[i].p_type == PT_INTERP) { if (strlen (argv[2]) + 1> ph[i].p_filesz) { return -5; } if (lseek (fd, ph[i].p_offset, SEEK_SET) == -1) { return -6; } char *interp = malloc (ph[i].p_filesz); memset (interp, 0, ph[i].p_filesz); memcpy (interp, argv[2], strlen (argv[2])); if (write (fd, argv[2], ph[i].p_filesz) != ph[i].p_filesz) { return -7; } if (lseek (fd, header.e_phoff + ((long)&ph[i].p_filesz - (long)ph), SEEK_SET) == -1) { return -8; } ElfW(Xword) filesz = strlen (argv[2])+1; if (write (fd, &filesz, sizeof(filesz)) != sizeof(filesz)) { return -9; } if (lseek (fd, header.e_phoff + ((long)&ph[i].p_memsz-(long)ph), SEEK_SET) == -1) { return -10; } ElfW(Xword) memsz = strlen (argv[2])+1; if (write (fd, &memsz, sizeof(memsz)) != sizeof(memsz)) { return -11; } return 0; } } return 0; } ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2009-01-12 15:08 UTC | newest] Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-12-18 21:42 how to make gdb happy with my linkmap Mathieu Lacage 2008-12-18 21:49 ` Daniel Jacobowitz 2008-12-18 22:03 ` Mathieu Lacage 2008-12-18 22:10 ` Daniel Jacobowitz 2008-12-26 10:40 ` Mathieu Lacage 2008-12-26 12:54 ` Daniel Jacobowitz 2009-01-05 14:58 ` Mathieu Lacage 2009-01-05 17:13 ` Daniel Jacobowitz 2009-01-07 16:46 ` Doug Evans 2009-01-12 15:08 ` Mathieu Lacage
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox