1 /* Handle ROCm Code Objects for GDB, the GNU Debugger.
3 Copyright (C) 2019-2020 Free Software Foundation, Inc.
4 Copyright (C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
23 #include "arch-utils.h"
28 #include "observable.h"
29 #include "rocm-tdep.h"
30 #include "solib-svr4.h"
38 #define ROCM_DSO_NAME_PREFIX "AMDGPU shared object [loaded from memory "
40 #define ROCM_DSO_NAME_SUFFIX "]"
42 /* ROCm-specific inferior data. */
46 /* List of code objects loaded into the inferior. */
47 struct so_list
*solib_list
;
50 /* Per-inferior data key. */
51 static const struct inferior_key
<solib_info
> rocm_solib_data
;
53 struct target_so_ops rocm_solib_ops
;
55 /* Free the solib linked list. */
58 rocm_free_solib_list (struct solib_info
*info
)
60 while (info
->solib_list
!= NULL
)
62 struct so_list
*next
= info
->solib_list
->next
;
64 free_so (info
->solib_list
);
65 info
->solib_list
= next
;
68 info
->solib_list
= NULL
;
71 /* Fetch the solib_info data for the current inferior. */
73 static struct solib_info
*
76 struct inferior
*inf
= current_inferior ();
78 struct solib_info
*info
= rocm_solib_data
.get (inf
);
80 info
= rocm_solib_data
.emplace (inf
);
85 /* Relocate section addresses. */
88 rocm_solib_relocate_section_addresses (struct so_list
*so
,
89 struct target_section
*sec
)
91 if (!rocm_is_amdgcn_gdbarch (gdbarch_from_bfd (so
->abfd
)))
93 svr4_so_ops
.relocate_section_addresses (so
, sec
);
97 lm_info_svr4
*li
= (lm_info_svr4
*)so
->lm_info
;
98 sec
->addr
= sec
->addr
+ li
->l_addr
;
99 sec
->endaddr
= sec
->endaddr
+ li
->l_addr
;
102 /* Make a deep copy of the solib linked list. */
104 static struct so_list
*
105 rocm_solib_copy_list (const struct so_list
*src
)
107 struct so_list
*dst
= NULL
;
108 struct so_list
**link
= &dst
;
112 struct so_list
*newobj
;
114 newobj
= XNEW (struct so_list
);
115 memcpy (newobj
, src
, sizeof (struct so_list
));
117 lm_info_svr4
*src_li
= (lm_info_svr4
*)src
->lm_info
;
118 newobj
->lm_info
= new lm_info_svr4 (*src_li
);
122 link
= &newobj
->next
;
130 /* Build a list of `struct so_list' objects describing the shared
131 objects currently loaded in the inferior. */
133 static struct so_list
*
134 rocm_solib_current_sos (void)
136 /* First, retrieve the host-side shared library list. */
137 struct so_list
*head
= svr4_so_ops
.current_sos ();
139 /* Then, the device-side shared library list. */
140 struct so_list
*list
= get_solib_info ()->solib_list
;
145 list
= rocm_solib_copy_list (list
);
150 /* Append our libraries to the end of the list. */
151 struct so_list
*tail
;
152 for (tail
= head
; tail
->next
; tail
= tail
->next
)
159 struct target_elf_image
161 /* The base address of the ELF file image in the inferior's memory. */
164 /* The size of the ELF file image. */
169 rocm_bfd_iovec_open (bfd
*nbfd
, void *open_closure
)
175 rocm_bfd_iovec_close (bfd
*nbfd
, void *stream
)
182 rocm_bfd_iovec_pread (bfd
*abfd
, void *stream
, void *buf
, file_ptr nbytes
,
185 CORE_ADDR addr
= ((target_elf_image
*)stream
)->base_addr
;
187 if (target_read_memory (addr
+ offset
, (gdb_byte
*)buf
, nbytes
) != 0)
189 bfd_set_error (bfd_error_invalid_operation
);
197 rocm_bfd_iovec_stat (bfd
*abfd
, void *stream
, struct stat
*sb
)
199 memset (sb
, '\0', sizeof (struct stat
));
200 sb
->st_size
= ((struct target_elf_image
*)stream
)->size
;
204 static gdb_bfd_ref_ptr
205 rocm_solib_bfd_open (const char *pathname
)
207 struct target_elf_image
*open_closure
;
210 /* Handle regular SVR4 libraries. */
211 if (strstr (pathname
, ROCM_DSO_NAME_PREFIX
) != pathname
)
212 return svr4_so_ops
.bfd_open (pathname
);
214 /* Decode the start and end addresses. */
215 if (sscanf (pathname
+ sizeof (ROCM_DSO_NAME_PREFIX
) - 1, "0x%lx..0x%lx",
218 internal_error (__FILE__
, __LINE__
, "ROCm-GDB Error: bad DSO name: `%s'",
221 open_closure
= XNEW (struct target_elf_image
);
222 open_closure
->base_addr
= addr
;
223 open_closure
->size
= end
- addr
;
225 gdb_bfd_ref_ptr
abfd (gdb_bfd_openr_iovec (
226 pathname
, "elf64-amdgcn", rocm_bfd_iovec_open
, open_closure
,
227 rocm_bfd_iovec_pread
, rocm_bfd_iovec_close
, rocm_bfd_iovec_stat
));
229 /* Check bfd format. */
230 if (!bfd_check_format (abfd
.get (), bfd_object
))
231 error (_ ("`%s': not in executable format: %s"),
232 bfd_get_filename (abfd
.get ()), bfd_errmsg (bfd_get_error ()));
234 unsigned char osabi
= elf_elfheader (abfd
)->e_ident
[EI_OSABI
];
235 unsigned char osabiversion
= elf_elfheader (abfd
)->e_ident
[EI_ABIVERSION
];
237 /* Make a check if the code object in the elf is V3. ROCM-gdb has
238 support only for V3. */
239 if (osabi
!= ELFOSABI_AMDGPU_HSA
)
240 error (_ ("`%s': ELF file OS ABI invalid (%d)."),
241 bfd_get_filename (abfd
.get ()), osabi
);
243 if (osabi
== ELFOSABI_AMDGPU_HSA
&& osabiversion
< 1)
244 error (_ ("`%s': ELF file ABI version (%d) is not supported."),
245 bfd_get_filename (abfd
.get ()), osabiversion
);
251 rocm_solib_create_inferior_hook (int from_tty
)
253 rocm_free_solib_list (get_solib_info ());
255 svr4_so_ops
.solib_create_inferior_hook (from_tty
);
259 rocm_update_solib_list ()
261 amd_dbgapi_process_id_t process_id
= get_amd_dbgapi_process_id ();
262 solib_info
*info
= get_solib_info ();
263 amd_dbgapi_status_t status
;
265 rocm_free_solib_list (info
);
266 struct so_list
**link
= &info
->solib_list
;
268 amd_dbgapi_code_object_id_t
*code_object_list
;
271 if ((status
= amd_dbgapi_code_object_list (process_id
, &count
,
272 &code_object_list
, nullptr))
273 != AMD_DBGAPI_STATUS_SUCCESS
)
275 warning (_ ("amd_dbgapi_code_object_list failed (%d)"), status
);
279 for (size_t i
= 0; i
< count
; ++i
)
281 struct so_list
*so
= XCNEW (struct so_list
);
282 lm_info_svr4
*li
= new lm_info_svr4
;
287 if (amd_dbgapi_code_object_get_info (
288 process_id
, code_object_list
[i
],
289 AMD_DBGAPI_CODE_OBJECT_INFO_LOAD_ADDRESS
, sizeof (li
->l_addr
),
291 != AMD_DBGAPI_STATUS_SUCCESS
292 || amd_dbgapi_code_object_get_info (
293 process_id
, code_object_list
[i
],
294 AMD_DBGAPI_CODE_OBJECT_INFO_URI_NAME
, sizeof (uri_bytes
),
296 != AMD_DBGAPI_STATUS_SUCCESS
)
299 /* FIXME: We need to properly decode the URI. */
301 std::string
uri (uri_bytes
);
304 size_t address_pos
= uri
.find ("://");
305 if (address_pos
== std::string::npos
)
309 size_t fragment_pos
= uri
.find ('#', address_pos
);
310 if (address_pos
== std::string::npos
)
313 std::string fragment
= uri
.substr (fragment_pos
);
315 /* Decode the offset and size. */
316 amd_dbgapi_global_address_t mem_addr
;
317 amd_dbgapi_size_t mem_size
;
319 if (sscanf (fragment
.c_str (), "#offset=0x%lx&size=0x%lx", &mem_addr
,
322 internal_error (__FILE__
, __LINE__
,
323 "ROCm-GDB Error: bad DSO name: `%s'", uri
.c_str ());
325 xsnprintf (so
->so_name
, sizeof so
->so_name
,
326 ROCM_DSO_NAME_PREFIX
"%s..%s" ROCM_DSO_NAME_SUFFIX
,
327 hex_string (mem_addr
), hex_string (mem_addr
+ mem_size
));
328 strcpy (so
->so_original_name
, so
->so_name
);
335 xfree (code_object_list
);
337 /* Force GDB to reload the solibs. */
338 clear_program_space_solib_cache (current_inferior ()->pspace
);
340 /* Switch terminal for any messages produced by
341 breakpoint_re_set. */
342 target_terminal::ours_for_output ();
344 solib_add (NULL
, 0, auto_solib_add
);
346 /* Switch it back. */
347 target_terminal::inferior ();
351 rocm_solib_dbgapi_activated ()
353 if (rocm_solib_ops
.current_sos
== NULL
)
355 /* Override what we need to */
356 rocm_solib_ops
= svr4_so_ops
;
357 rocm_solib_ops
.current_sos
= rocm_solib_current_sos
;
358 rocm_solib_ops
.solib_create_inferior_hook
359 = rocm_solib_create_inferior_hook
;
360 rocm_solib_ops
.bfd_open
= rocm_solib_bfd_open
;
361 rocm_solib_ops
.relocate_section_addresses
362 = rocm_solib_relocate_section_addresses
;
365 /* Engage the ROCm so_ops. */
366 set_solib_ops (target_gdbarch (), &rocm_solib_ops
);
370 rocm_solib_dbgapi_deactivated ()
372 /* Disengage the ROCm so_ops. */
373 set_solib_ops (target_gdbarch (), &svr4_so_ops
);
377 rocm_solib_target_inferior_created (struct target_ops
*target
, int from_tty
)
379 rocm_free_solib_list (get_solib_info ());
380 rocm_update_solib_list ();
383 /* -Wmissing-prototypes */
384 extern initialize_file_ftype _initialize_rocm_solib
;
387 _initialize_rocm_solib (void)
389 /* Install our observers. */
390 amd_dbgapi_activated
.attach (rocm_solib_dbgapi_activated
);
391 amd_dbgapi_deactivated
.attach (rocm_solib_dbgapi_deactivated
);
392 amd_dbgapi_code_object_list_updated
.attach (rocm_update_solib_list
);
394 /* FIXME: remove this when we can clear the solist in
395 rocm_solib_create_inferior_hook. */
396 gdb::observers::inferior_created
.attach (rocm_solib_target_inferior_created
);