1 /* This test program is part of GDB, the GNU debugger.
3 Copyright 2011 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /* Simulate loading of JIT code. */
41 struct jit_code_entry
*next_entry
;
42 struct jit_code_entry
*prev_entry
;
43 const char *symfile_addr
;
44 uint64_t symfile_size
;
50 /* This type should be jit_actions_t, but we use uint32_t
51 to be explicit about the bitwidth. */
53 struct jit_code_entry
*relevant_entry
;
54 struct jit_code_entry
*first_entry
;
57 /* GDB puts a breakpoint in this function. */
58 void __attribute__((noinline
)) __jit_debug_register_code () { }
60 /* Make sure to specify the version statically, because the
61 debugger may check the version before we can set it. */
62 struct jit_descriptor __jit_debug_descriptor
= { 1, 0, 0, 0 };
65 usage (const char *const argv0
)
67 fprintf (stderr
, "Usage: %s library [count]\n", argv0
);
71 /* Update .p_vaddr and .sh_addr as if the code was JITted to ADDR. */
74 update_locations (const void *const addr
, int idx
)
76 const ElfW (Ehdr
) *const ehdr
= (ElfW (Ehdr
) *)addr
;
77 ElfW (Shdr
) *const shdr
= (ElfW (Shdr
) *)((char *)addr
+ ehdr
->e_shoff
);
78 ElfW (Phdr
) *const phdr
= (ElfW (Phdr
) *)((char *)addr
+ ehdr
->e_phoff
);
81 for (i
= 0; i
< ehdr
->e_phnum
; ++i
)
82 if (phdr
[i
].p_type
== PT_LOAD
)
83 phdr
[i
].p_vaddr
+= (ElfW (Addr
))addr
;
85 for (i
= 0; i
< ehdr
->e_shnum
; ++i
)
87 if (shdr
[i
].sh_type
== SHT_STRTAB
)
89 /* Note: we update both .strtab and .dynstr. The latter would
90 not be correct if this were a regular shared library (.hash
91 would be wrong), but this is a simulation -- the library is
92 never exposed to the dynamic loader, so it all ends up ok. */
93 char *const strtab
= (char *)((ElfW (Addr
))addr
+ shdr
[i
].sh_offset
);
94 char *const strtab_end
= strtab
+ shdr
[i
].sh_size
;
97 for (p
= strtab
; p
< strtab_end
; p
+= strlen (p
) + 1)
98 if (strcmp (p
, "jit_function_XXXX") == 0)
99 sprintf (p
, "jit_function_%04d", idx
);
102 if (shdr
[i
].sh_flags
& SHF_ALLOC
)
103 shdr
[i
].sh_addr
+= (ElfW (Addr
))addr
;
108 main (int argc
, char *argv
[])
110 /* These variables are here so they can easily be set from jit.exp. */
111 const char *libname
= NULL
;
114 count
= count
; /* gdb break here 0 */
124 /* Only set if not already set from GDB. */
127 if (argc
> 2 && count
== 0)
128 /* Only set if not already set from GDB. */
129 count
= atoi (argv
[2]);
131 printf ("%s:%d: libname = %s, count = %d\n", __FILE__
, __LINE__
,
134 if ((fd
= open (libname
, O_RDONLY
)) == -1)
136 fprintf (stderr
, "open (\"%s\", O_RDONLY): %s\n", libname
,
141 if (fstat (fd
, &st
) != 0)
143 fprintf (stderr
, "fstat (\"%d\"): %s\n", fd
, strerror (errno
));
147 for (i
= 0; i
< count
; ++i
)
149 const void *const addr
= mmap (0, st
.st_size
, PROT_READ
|PROT_WRITE
,
151 struct jit_code_entry
*const entry
= calloc (1, sizeof (*entry
));
153 if (addr
== MAP_FAILED
)
155 fprintf (stderr
, "mmap: %s\n", strerror (errno
));
159 update_locations (addr
, i
);
161 /* Link entry at the end of the list. */
162 entry
->symfile_addr
= (const char *)addr
;
163 entry
->symfile_size
= st
.st_size
;
164 entry
->prev_entry
= __jit_debug_descriptor
.relevant_entry
;
165 __jit_debug_descriptor
.relevant_entry
= entry
;
167 if (entry
->prev_entry
!= NULL
)
168 entry
->prev_entry
->next_entry
= entry
;
170 __jit_debug_descriptor
.first_entry
= entry
;
173 __jit_debug_descriptor
.action_flag
= JIT_REGISTER_FN
;
174 __jit_debug_register_code ();
177 i
= 0; /* gdb break here 1 */
179 /* Now unregister them all in reverse order. */
180 while (__jit_debug_descriptor
.relevant_entry
!= NULL
)
182 struct jit_code_entry
*const entry
=
183 __jit_debug_descriptor
.relevant_entry
;
184 struct jit_code_entry
*const prev_entry
= entry
->prev_entry
;
186 if (prev_entry
!= NULL
)
188 prev_entry
->next_entry
= NULL
;
189 entry
->prev_entry
= NULL
;
192 __jit_debug_descriptor
.first_entry
= NULL
;
195 __jit_debug_descriptor
.action_flag
= JIT_UNREGISTER_FN
;
196 __jit_debug_register_code ();
198 __jit_debug_descriptor
.relevant_entry
= prev_entry
;
202 return 0; /* gdb break here 2 */