HwDbgInfo_debug hsail_init_hwdbginfo(HsailNotificationPayload* payload) { struct ui_out *uiout = NULL; /* pointer to shared memory*/ void* pShm = NULL; /* HwDbgFacilities objects */ HwDbgInfo_err errout_twolevel= HWDBGINFO_E_UNEXPECTED; HwDbgInfo_err errout_onelevel= HWDBGINFO_E_UNEXPECTED; HwDbgInfo_debug dbg_op = NULL; const int max_shared_mem_size = hsail_get_agent_binary_shmem_max_size(); if (payload == NULL) { /* return the cached dbgInfo there exists */ return gs_DbgInfo; } gdb_assert(payload->m_Notification == HSAIL_NOTIFY_NEW_BINARY); uiout = current_uiout; /* Shared memory buffer pointer*/ dbg_op = NULL; if(hsail_is_debug_facilities_loaded()) { /* A copy of the shared memory segment )*/ void* dbe_binary = NULL; size_t dbe_binary_size = 0; int shmid = -1; hsail_segment_update_loadmap(); /*1M used is hard wired for now*/ shmid = shmget(hsail_get_agent_binary_shmem_key(), max_shared_mem_size, 0666); if (shmid <= 0) { ui_out_text(uiout, "GDB: HwDbgFacilities init: shmid is invalid\n"); } gdb_assert(shmid > 0); /* Get shm pointer */ pShm = (int*)shmat(shmid, NULL, 0); if (pShm == NULL) { ui_out_text(uiout, "GDB: HwDbgFacilities init: pShm is NULL\n"); } gdb_assert(pShm != NULL); dbe_binary_size = ((size_t*)pShm)[0]; gdb_assert(dbe_binary_size > 0 && dbe_binary_size < max_shared_mem_size); dbe_binary = xmalloc(dbe_binary_size); gdb_assert(dbe_binary != NULL); memcpy(dbe_binary,(size_t*)pShm+1,dbe_binary_size); /* Uncomment this call if you need to save the binary to the file hsail_breakpoint_save_binary_to_file(dbe_binary_size, dbe_binary); */ /* Attempt to initialize as a HSAIL backend binary*/ dbg_op = hwdbginfo_init_with_hsa_1_0_binary(dbe_binary, dbe_binary_size, &errout_twolevel); /* Keep this printf here as a reminder for a * quick way to check that the IPC happened correctly*/ /* int i = 0; for(i = 0; i<10;i++) { printf("%d \t %d\n",i,*((int*)dbe_binary + i)); } */ /* If we get a no HL binary, return code, we try to initialize as a single level binary */ if (errout_twolevel == HWDBGINFO_E_NOHLBINARY) { /* dbg_op = hwdbginfo_init_with_single_level_binary(dbe_binary, dbe_binary_size, &errout_onelevel); */ dbg_op = NULL; } /* * In the near future, debug facilities needs to be able to tell the difference * between an incomplete 2 level code object and a complete 1 level code object. * Since we dont support debugging LC for 1.3, this is not a big issue. * */ /* If we have a single level binary, thats good, we dont need to check the * two level return code */ if (errout_twolevel == HWDBGINFO_E_NOHLBINARY && errout_onelevel == HWDBGINFO_E_SUCCESS) { fflush(stdout); } else if (errout_twolevel != HWDBGINFO_E_SUCCESS ) { /* HwDbgFacilities init: Called DebugFacilities Incorrectly. * We can add more detailed messages such as low-level dwarf or high level dwarf missing in the future * */ ui_out_text(uiout, "[ROCm-gdb]: The code object for the current dispatch does not contain debug information\n"); fflush(stdout); dbg_op = NULL; } /* Test function to print all the mapped addresses and line numbers */ /* hsail_dbginfo_test_all_mapped_addrs(dbg_op); */ /* We can clear the dbe_binary buffer once we have initialized HWDbgFacilities */ if (dbe_binary != NULL) { free_current_contents(&dbe_binary); } /* Get the kernel source, only if the 2 level initialization was good*/ if (errout_twolevel == HWDBGINFO_E_SUCCESS) { if (!hsail_dbginfo_init_source_buffer(dbg_op)) { ui_out_text(uiout, "[ROCm-gdb]: HwDbgFacilities get hsail text error\n"); } } /* Detach shared memory */ if (shmdt(pShm) == -1) { ui_out_text(uiout, "GDB: HwDbgFacilities init: Error detaching shm\n"); } } /* cache the dgbInfo */ gs_DbgInfo = dbg_op; return gs_DbgInfo; /* * This function's caller will use the returned context to query the * Debug Facilities API */ }
/* Updates the kernel_source_file_name and saves the kernel to the file * */ static void hsail_kernel_save_source_to_file(struct hsail_kernel* k) { int filename_str_len = 0; char* hsail_source_buffer = NULL; FILE* temp_file_handle = NULL; const char hsail_ext[] = "temp_source"; filename_str_len = strlen(hsail_ext) + 1; gdb_assert(NULL != k); free_current_contents(&k->kernel_source_file_name); k->kernel_source_file_name = (char*)xmalloc(sizeof(char)*filename_str_len); gdb_assert(NULL != k->kernel_source_file_name); memset(k->kernel_source_file_name, '\0', filename_str_len); strcpy(k->kernel_source_file_name, hsail_ext); /* Two other possible directions are below*/ /* Case 1: Implementation where we generate BRIGModule_#Number#.hsail * * The better version for this would be to use an API in debug facilities that gets module name * from kernel name. That'd allow gdb to be aware of "is this a new kernel" * or "is this a new module" and accordingly skip creating a text file. * The 64 below adds some space for a "index" and underscore. */ /* const char hsail_prefix[] = "BrigModule"; static int module_index = 0; filename_str_len = strlen(hsail_ext) + strlen(hsail_prefix) + 64; k->kernel_source_file_name = (char*)xmalloc(sizeof(char)*filename_str_len); memset(k->kernel_source_file_name, '\0',filename_str_len); snprintf(k->kernel_source_file_name,filename_str_len, "%s_%d%s",hsail_prefix, module_index, hsail_ext); module_index = module_index +1; */ /* Case 2: Implementation where we generate kernel_#KernelName#.hsail * * The below logic can be used to save kernels based on the dispatched kernel name. * However, it is not great since the file we save is HSAIL text for a BRIG module * and each could have multiple kernels internally * */ /* const char hsail_prefix[] = "Kernel_"; gdb_assert(k!=NULL); gdb_assert(k->kernel_name != NULL); filename_str_len = strlen(k->kernel_name) + strlen(hsail_ext) + strlen(hsail_prefix); k->kernel_source_file_name = (char*)xmalloc(sizeof(char)*filename_str_len); memset(k->kernel_source_file_name, '\0',filename_str_len); strcpy(k->kernel_source_file_name, hsail_prefix); strcat(k->kernel_source_file_name, k->kernel_name); strcat(k->kernel_source_file_name, hsail_ext); */ hsail_source_buffer = hsail_dbginfo_get_source_buffer(); gdb_assert(hsail_source_buffer!= NULL); temp_file_handle = fopen(k->kernel_source_file_name,"wb"); gdb_assert(temp_file_handle != NULL); fprintf(temp_file_handle, "%s",hsail_source_buffer); rewind(temp_file_handle); fclose(temp_file_handle); printf_filtered("HSAIL kernel saved to %s\n",k->kernel_source_file_name); /* Once we write, we should somehow change the permission of this file to be readonly * */ }
static bool hsail_dbginfo_init_source_buffer(HwDbgInfo_debug dbg_op) { struct ui_out *uiout = NULL; bool ret_code = false; /* Get the kernel source */ const char* temp_hsail_src = NULL; uint64_t hsail_source_len = 0; HwDbgInfo_err errOut = hwdbginfo_get_hsail_text(dbg_op, &temp_hsail_src, &hsail_source_len); if (errOut == HWDBGINFO_E_SUCCESS) { gdb_assert(temp_hsail_src != NULL); gdb_assert(hsail_source_len != 0); if (gs_hsail_source == NULL) { gs_hsail_source = xmalloc((hsail_source_len+1)*sizeof(char)); } else { /* We need to resize the kernel source buffer for the new hwdbginfo object */ free_current_contents(&gs_hsail_source); gs_hsail_source = xmalloc((hsail_source_len+1)*sizeof(char)); } gdb_assert(gs_hsail_source != NULL); memset(gs_hsail_source, '\0', (hsail_source_len+1)*sizeof(char)); memcpy(gs_hsail_source, temp_hsail_src, hsail_source_len*sizeof(char)); ret_code = hsail_dbginfo_save_source_to_file(); if (ret_code == true) { rocm_printf_filtered("Kernel saved to %s\n", active_kernel_src_file_path); } else { rocm_printf_filtered("Error saving kernel\n"); } } else { size_t buffer_len = 1024; size_t file_name_len = 0; char* file_name = (char*)xmalloc(sizeof(char)*buffer_len); gdb_assert(file_name != NULL); memset(file_name, '\0', sizeof(char)*buffer_len); errOut = hwdbginfo_first_file_name(dbg_op, buffer_len, file_name, &file_name_len); if (errOut != HWDBGINFO_E_SUCCESS) { printf_filtered("Could not get the first filename "); } else { size_t source_len = 0; gdb_assert(errOut == HWDBGINFO_E_SUCCESS); hsail_utils_copy_string(&active_kernel_src_file_path, file_name); ret_code = hsail_utils_read_file_to_array(active_kernel_src_file_path, &gs_hsail_source, &source_len); if (ret_code == false) { rocm_printf_filtered("Could not read %s\n", active_kernel_src_file_path); } xfree(file_name); } } return ret_code; }