diff --git a/gdb/auto-load.c b/gdb/auto-load.c index 198bb073a1ba..4a577f88219f 100644 --- a/gdb/auto-load.c +++ b/gdb/auto-load.c @@ -43,6 +43,11 @@ #include "gdbsupport/pathstuff.h" #include "cli/cli-style.h" +#ifdef __amigaos4__ +#define AUTO_LOAD_DIR "$debugdir;$datadir/auto-load" +#define AUTO_LOAD_SAFE_PATH AUTO_LOAD_DIR +#endif + /* The section to look in for auto-loaded scripts (in file formats that support sections). Each entry in this section is a record that begins with a leading byte diff --git a/gdb/charset.c b/gdb/charset.c index a6261fc505c4..7c2f245a6114 100644 --- a/gdb/charset.c +++ b/gdb/charset.c @@ -1007,6 +1007,12 @@ _initialize_charset () which GNU libiconv doesn't like (infinite loop). */ if (!strcmp (auto_host_charset_name, "646") || !*auto_host_charset_name) auto_host_charset_name = "ASCII"; +#ifdef __amigaos4__ + /* clib4's nl_langinfo(CODESET) returns "ISO-8859-1" but its iconv + implementation cannot reliably convert ISO-8859-1 to/from UTF-32. + Force UTF-8 which clib4's iconv handles correctly. */ + auto_host_charset_name = "UTF-8"; +#endif auto_target_charset_name = auto_host_charset_name; #elif defined (USE_WIN32API) { diff --git a/gdb/filesystem.c b/gdb/filesystem.c index 2cb938d29ba6..5bb27867d57b 100644 --- a/gdb/filesystem.c +++ b/gdb/filesystem.c @@ -120,7 +120,14 @@ starting the forward slash (`/') character are considered absolute,\n\ and the directory separator character is the forward slash (`/'). If\n\ `dos-based', target file names starting with a drive letter followed\n\ by a colon (e.g., `c:'), are also considered absolute, and the\n\ -backslash (`\\') is also considered a directory separator. Set to\n\ +backslash (`\\') is also considered a directory separator. If\n\ +`amiga-based', target file names starting with a drive name followed\n\ +by a colon (e.g., `sys:'), are also considered absolute, and the\n\ +directory separator character is the forward slash (`/'). Set to\n\ +backslash (`\\') is also considered a directory separator. If\n\ +`amiga-based', target file names starting with a drive name followed\n\ +by a colon (e.g., `sys:'), are also considered absolute, and the\n\ +directory separator character is the forward slash (`/'). Set to\n\ `auto' (which is the default), to let GDB decide, based on its\n\ knowledge of the target operating system."), #endif diff --git a/gdb/filesystem.h b/gdb/filesystem.h index 176911aeef99..1a0f3457c156 100644 --- a/gdb/filesystem.h +++ b/gdb/filesystem.h @@ -51,6 +51,7 @@ extern const char *target_file_system_kind; #else #define IS_TARGET_ABSOLUTE_PATH(kind, p) \ (((kind) == file_system_kind_dos_based) ? IS_DOS_ABSOLUTE_PATH (p) \ + : ((kind) == file_system_kind_amigaos_based) ? IS_AMIGOS_ABSOLUTE_PATH(p) \ : IS_UNIX_ABSOLUTE_PATH (p)) #endif @@ -65,6 +66,7 @@ extern const char *target_file_system_kind; #else #define HAS_TARGET_DRIVE_SPEC(kind, p) \ (((kind) == file_system_kind_dos_based) ? HAS_DOS_DRIVE_SPEC (p) \ + : ((kind) == file_system_kind_amigaos_based) ? HAS_AMIGOS_DRIVE_SPEC(p) \ : 0) #endif diff --git a/gdb/ppc-amigaos-nat.c b/gdb/ppc-amigaos-nat.c index 67701a6f34f8..8807bae3c4a9 100644 --- a/gdb/ppc-amigaos-nat.c +++ b/gdb/ppc-amigaos-nat.c @@ -30,7 +30,7 @@ #include "ppc-tdep.h" #include "gdbsupport/ptid.h" #include "gdbsupport/gdb_wait.h" - + #include #include #include @@ -61,7 +61,7 @@ const struct regset ppc_amigaos_vrregset = regcache_collect_regset }; -// From clib4 , bucket list to clear up +/* ELF library references provided by clib4 runtime */ extern struct Library *ElfBase; extern struct ElfIFace *IElf; @@ -108,13 +108,26 @@ class ppc_amigaos_nat_target : public inf_child_target /** * Get an empty message and initialize it. - * @return + * + * No locking required: the debug callback (alloc) runs in the + * debuggee's task context and suspends it immediately after + * PutMsg, while free_message runs in the debugger's wait() after + * the debuggee is already suspended. The pool is therefore + * accessed sequentially by design. If multi-debuggee support + * is added in the future, a Mutex would be appropriate here + * (not Forbid/Permit which locks the entire OS). */ struct debugger_message * alloc_message ( struct Process *process ) { struct debugger_message *message = (struct debugger_message *)IExec->RemHead(amigaos_debug_messages_list); + if (!message) + { + IExec->DebugPrintF("[GDB] WARNING: message pool exhausted! Dropping debug event for task %p\n", process); + return NULL; + } + message->msg.mn_Node.ln_Type = NT_MESSAGE; message->msg.mn_Node.ln_Name = NULL; message->msg.mn_ReplyPort = NULL; @@ -125,11 +138,8 @@ class ppc_amigaos_nat_target : public inf_child_target } /** - * Return a message to the pool. Note that we disable here so that we're not - * interrupted. Can't use semaphores because get_msg_packet is called during an - * exception. - * - * @param msg + * Return a message to the pool. See alloc_message comment for + * why no locking is needed. */ void free_message( struct debugger_message *message ) @@ -142,7 +152,7 @@ class ppc_amigaos_nat_target : public inf_child_target ppc_amigaos_nat_target (); ~ppc_amigaos_nat_target () override; - + ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override; void fetch_registers (struct regcache *, int) override; @@ -178,8 +188,7 @@ class ppc_amigaos_nat_target : public inf_child_target } */ - // TODO: ? void prepare_to_store (regcache *regs) override; - // TODO: ? int async_wait_fd () override + /* Not needed: prepare_to_store() and async_wait_fd() use defaults */ void resume (ptid_t ptid,int step,enum gdb_signal signal) override { @@ -203,16 +212,19 @@ class ppc_amigaos_nat_target : public inf_child_target IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d ( task: %p )\n"),__func__,__LINE__,task ).c_str()); - if( task ) + if( task ) { - /* Clear the debug hook (necessary to avoid the shell reusing it) */ - IDebug->AddDebugHook ( task,NULL ); - - // ML: According to the dos Autodoc DeleteTask/RemTask shouldn't be used on Process, but no other API avaiblle - IExec->DeleteTask ( task ); + /* Clear the debug hook first */ + IDebug->AddDebugHook ( task, NULL ); + + /* Signal the process to break, then restart it so it can + process the signal and exit via its normal shutdown path. + This is safer than DeleteTask on a Process. */ + IExec->Signal ( task, SIGBREAKF_CTRL_C ); + IExec->RestartTask ( task, 0 ); } - target_mourn_inferior(inferior_ptid); + target_mourn_inferior(inferior_ptid); } /* @@ -238,7 +250,7 @@ class ppc_amigaos_nat_target : public inf_child_target } */ - // TODO: char *pid_to_exec_file (int pid) override; + /* Not yet implemented: pid_to_exec_file() for 'info proc' support */ /* bool info_proc (const char *args, enum info_proc_what what) override @@ -568,9 +580,10 @@ ppc_amigaos_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,t case GDB_SIGNAL_INT: case GDB_SIGNAL_FPE: case GDB_SIGNAL_ILL: - case GDB_SIGNAL_ALRM: - { - ourstatus->set_stopped (GDB_SIGNAL_0); + case GDB_SIGNAL_ALRM: + { + /* Preserve the actual signal so GDB can report the exception type */ + ourstatus->set_stopped ((enum gdb_signal)debuggerMessage->signal); break; } @@ -611,59 +624,74 @@ ppc_amigaos_nat_target::fetch_registers (struct regcache *regcache, int regno) if( regno == -1 ) { - for (int i = 0; i < 31; i++) - regcache->raw_supply (regno, (void*)&context.gpr[i]); + /* Supply all GPRs (r0-r31) */ + for (int i = 0; i < 32; i++) + regcache->raw_supply (tdep->ppc_gp0_regnum + i, (void*)&context.gpr[i]); - for (int i = 0; i < 31; i++) - regcache->raw_supply (regno, (void*)&context.fpr[i]); + /* Supply all FPRs (f0-f31) */ + if (tdep->ppc_fp0_regnum >= 0) + { + for (int i = 0; i < 32; i++) + regcache->raw_supply (tdep->ppc_fp0_regnum + i, (void*)&context.fpr[i]); + } + /* Supply special registers */ regcache->raw_supply (gdbarch_pc_regnum (gdbarch), (void *)&context.ip); regcache->raw_supply (tdep->ppc_ps_regnum, (void *)&context.msr); regcache->raw_supply (tdep->ppc_cr_regnum, (void *)&context.cr); regcache->raw_supply (tdep->ppc_lr_regnum, (void *)&context.lr); regcache->raw_supply (tdep->ppc_ctr_regnum, (void *)&context.ctr); regcache->raw_supply (tdep->ppc_xer_regnum, (void *)&context.xer); - regcache->raw_supply (tdep->ppc_fpscr_regnum, (void *)&context.fpscr); + if (tdep->ppc_fpscr_regnum >= 0) + regcache->raw_supply (tdep->ppc_fpscr_regnum, (void *)&context.fpscr); - if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1) + /* Supply AltiVec registers if available */ + if (tdep->ppc_vr0_regnum != -1 && tdep->ppc_vrsave_regnum != -1 + && (context.Flags & ECF_VECTOR)) { - ppc_amigaos_vrregset.supply_regset( &ppc_amigaos_vrregset,regcache,regno,(void *)&context.vscr,PPC_AMIGAOS_SIZEOF_VRREGSET ); + ppc_amigaos_vrregset.supply_regset (&ppc_amigaos_vrregset, regcache, -1, (void *)&context.vscr, PPC_AMIGAOS_SIZEOF_VRREGSET); } } - else + else { - if (regno == gdbarch_pc_regnum (gdbarch) ) - { + if (regno == gdbarch_pc_regnum (gdbarch)) + { regcache->raw_supply (regno, (void*)&context.ip); } - else if (regno >= 0 && regno <= 31) + else if (regno >= tdep->ppc_gp0_regnum && regno < tdep->ppc_gp0_regnum + 32) { - regcache->raw_supply (regno, (void*)&context.gpr[regno]); + regcache->raw_supply (regno, (void*)&context.gpr[regno - tdep->ppc_gp0_regnum]); + } + else if (tdep->ppc_fp0_regnum >= 0 + && regno >= tdep->ppc_fp0_regnum && regno < tdep->ppc_fp0_regnum + 32) + { + regcache->raw_supply (regno, (void*)&context.fpr[regno - tdep->ppc_fp0_regnum]); } else if (altivec_register_p (gdbarch, regno)) { - ppc_amigaos_vrregset.supply_regset( &ppc_amigaos_vrregset,regcache,regno,(void *)&context.vscr,PPC_AMIGAOS_SIZEOF_VRREGSET ); + if (context.Flags & ECF_VECTOR) + ppc_amigaos_vrregset.supply_regset (&ppc_amigaos_vrregset, regcache, regno, (void *)&context.vscr, PPC_AMIGAOS_SIZEOF_VRREGSET); } - else if (regno >= 32 && regno <= 64) - regcache->raw_supply (regno, (void*)&context.fpr[regno]); else if (regno == tdep->ppc_ps_regnum) regcache->raw_supply (regno, (void *)&context.msr); else if (regno == tdep->ppc_cr_regnum) - regcache->raw_supply (tdep->ppc_cr_regnum, (void *)&context.cr); + regcache->raw_supply (regno, (void *)&context.cr); else if (regno == tdep->ppc_lr_regnum) - regcache->raw_supply (tdep->ppc_lr_regnum, (void *)&context.lr); - else if (regno == tdep->ppc_ctr_regnum) - regcache->raw_supply (tdep->ppc_ctr_regnum, (void *)&context.ctr); + regcache->raw_supply (regno, (void *)&context.lr); + else if (regno == tdep->ppc_ctr_regnum) + regcache->raw_supply (regno, (void *)&context.ctr); else if (regno == tdep->ppc_xer_regnum) - regcache->raw_supply (tdep->ppc_xer_regnum, (void *)&context.xer); - else if (regno == tdep->ppc_fpscr_regnum) - regcache->raw_supply (tdep->ppc_fpscr_regnum, (void *)&context.fpscr); - else if (regno == tdep->ppc_vr0_regnum) - regcache->raw_supply (tdep->ppc_vr0_regnum, (void *)&context.vr ); - else if (regno == tdep->ppc_vrsave_regnum) - regcache->raw_supply (tdep->ppc_vrsave_regnum, (void *)&context.vrsave ); + regcache->raw_supply (regno, (void *)&context.xer); + else if (tdep->ppc_fpscr_regnum >= 0 && regno == tdep->ppc_fpscr_regnum) + regcache->raw_supply (regno, (void *)&context.fpscr); + else if (tdep->ppc_vrsave_regnum >= 0 && regno == tdep->ppc_vrsave_regnum) + regcache->raw_supply (regno, (void *)&context.vrsave); else { + /* Unknown register — supply zeros rather than crashing */ + IExec->DebugPrintF("[GDB] %s: unknown register %d ('%s'), supplying zero\n", + __func__, regno, gdbarch_register_name (gdbarch, regno)); + internal_error (_("fetch_registers: unexpected register: '%s'"),gdbarch_register_name ( gdbarch,regno )); } } @@ -672,16 +700,110 @@ ppc_amigaos_nat_target::fetch_registers (struct regcache *regcache, int regno) void ppc_amigaos_nat_target::store_registers (struct regcache *regcache, int regno) { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Todo ( regcache: %p, regno: %d)\n"),__func__,__LINE__,regcache,regno ).c_str()); + struct gdbarch *gdbarch = regcache->arch (); + ppc_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + struct Task *task = (struct Task *)regcache->ptid().pid(); + + IExec->DebugPrintF( string_printf (_("[GDB] %s ( regcache: %p, regno: %d (%s), task: %p)\n"), + __func__, regcache, regno, gdbarch_register_name (gdbarch, regno), task.c_str() ) ); + + /* Read current context so we only modify the requested register(s) */ + struct ExceptionContext context; + uint32 read_flags = RTCF_INFO | RTCF_SPECIAL | RTCF_STATE | RTCF_GENERAL | RTCF_FPU; + IDebug->ReadTaskContext (task, &context, read_flags); + + uint32 write_flags = 0; + + if (regno == -1) + { + /* Store all GPRs */ + for (int i = 0; i < 32; i++) + regcache->raw_collect (tdep->ppc_gp0_regnum + i, (void*)&context.gpr[i]); + write_flags |= RTCF_GENERAL; + + /* Store all FPRs */ + if (tdep->ppc_fp0_regnum >= 0) + { + for (int i = 0; i < 32; i++) + regcache->raw_collect (tdep->ppc_fp0_regnum + i, (void*)&context.fpr[i]); + write_flags |= RTCF_FPU; + } + + /* Store special registers */ + regcache->raw_collect (gdbarch_pc_regnum (gdbarch), (void *)&context.ip); + regcache->raw_collect (tdep->ppc_ps_regnum, (void *)&context.msr); + regcache->raw_collect (tdep->ppc_cr_regnum, (void *)&context.cr); + regcache->raw_collect (tdep->ppc_lr_regnum, (void *)&context.lr); + regcache->raw_collect (tdep->ppc_ctr_regnum, (void *)&context.ctr); + regcache->raw_collect (tdep->ppc_xer_regnum, (void *)&context.xer); + if (tdep->ppc_fpscr_regnum >= 0) + regcache->raw_collect (tdep->ppc_fpscr_regnum, (void *)&context.fpscr); + write_flags |= RTCF_SPECIAL | RTCF_STATE; + } + else if (regno == gdbarch_pc_regnum (gdbarch)) + { + regcache->raw_collect (regno, (void *)&context.ip); + write_flags = RTCF_SPECIAL; + } + else if (regno >= tdep->ppc_gp0_regnum && regno < tdep->ppc_gp0_regnum + 32) + { + regcache->raw_collect (regno, (void*)&context.gpr[regno - tdep->ppc_gp0_regnum]); + write_flags = RTCF_GENERAL; + } + else if (tdep->ppc_fp0_regnum >= 0 + && regno >= tdep->ppc_fp0_regnum && regno < tdep->ppc_fp0_regnum + 32) + { + regcache->raw_collect (regno, (void*)&context.fpr[regno - tdep->ppc_fp0_regnum]); + write_flags = RTCF_FPU; + } + else if (regno == tdep->ppc_ps_regnum) + { + regcache->raw_collect (regno, (void *)&context.msr); + write_flags = RTCF_SPECIAL; + } + else if (regno == tdep->ppc_cr_regnum) + { + regcache->raw_collect (regno, (void *)&context.cr); + write_flags = RTCF_SPECIAL; + } + else if (regno == tdep->ppc_lr_regnum) + { + regcache->raw_collect (regno, (void *)&context.lr); + write_flags = RTCF_SPECIAL; + } + else if (regno == tdep->ppc_ctr_regnum) + { + regcache->raw_collect (regno, (void *)&context.ctr); + write_flags = RTCF_SPECIAL; + } + else if (regno == tdep->ppc_xer_regnum) + { + regcache->raw_collect (regno, (void *)&context.xer); + write_flags = RTCF_SPECIAL; + } + else if (tdep->ppc_fpscr_regnum >= 0 && regno == tdep->ppc_fpscr_regnum) + { + regcache->raw_collect (regno, (void *)&context.fpscr); + write_flags = RTCF_FPU; + } + else + { + IExec->DebugPrintF("[GDB] %s: unknown register %d ('%s'), not writing\n", + __func__, regno, gdbarch_register_name (gdbarch, regno)); + + internal_error (_("store_registers: unknown register: '%s'"),gdbarch_register_name ( gdbarch,regno )); + // Needed? + return; + } + + if (write_flags) + IDebug->WriteTaskContext (task, &context, write_flags); } enum target_xfer_status ppc_amigaos_nat_target::xfer_partial (enum target_object object,const char *annex, gdb_byte *readbuf,const gdb_byte *writebuf,ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d called for memory tranfser at address: 0x%s for %s bytes (readbuf: %p, writebuf: %p, annex: '%s', object: %d )\n"),__func__,__LINE__,phex (offset, sizeof (offset)),pulongest (len), readbuf, writebuf, annex, object).c_str()); - - enum target_xfer_status result = TARGET_XFER_E_IO; - + IExec->DebugPrintF ( string_printf (_("[GDB] %s called for memory tranfser at address: 0x%s for %s bytes (readbuf: %p, writebuf: %p, annex: '%s', object: %d )\n"),__func__,phex (offset, sizeof (offset)),pulongest (len), readbuf, writebuf, annex, object).c_str()); switch (object) { @@ -690,7 +812,7 @@ ppc_amigaos_nat_target::xfer_partial (enum target_object object,const char *anne if (offset == 0) { // ML: Helps to unwind farme correctly - result = TARGET_XFER_E_IO; + return TARGET_XFER_E_IO; } else { @@ -699,31 +821,16 @@ ppc_amigaos_nat_target::xfer_partial (enum target_object object,const char *anne ULONG currentAttrs = IMMU->GetMemoryAttrs( (APTR)offset,0 ); IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Address 0x%s attributes 0x%s\n"),__func__,__LINE__,phex (offset, sizeof (offset)),phex (currentAttrs, sizeof (currentAttrs))).c_str()); - IMMU->SetMemoryAttrs ( (APTR)offset,len,currentAttrs & MEMATTRF_READ_WRITE ); + IMMU->SetMemoryAttrs ( (APTR)offset,len,MEMATTRF_READ_WRITE ); if (readbuf) { IExec->CopyMem( (APTR)offset,(APTR)readbuf,len ); - - result = TARGET_XFER_OK; } else // if(writebuf) { - ULONG modifiedAttrs = IMMU->GetMemoryAttrs( (APTR)offset,0 ); - - if( ( modifiedAttrs & MEMATTRF_RW_MASK ) == MEMATTRF_READ_ONLY ) - { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Could not modified Address 0x%s attributes 0x%s to allow writing\n"),__func__,__LINE__,phex (offset, sizeof (offset)),phex (modifiedAttrs, sizeof (modifiedAttrs))).c_str()); - - result = TARGET_XFER_UNAVAILABLE; - } - else - { - IExec->CopyMem( (APTR)writebuf,(APTR)offset,len ); - IExec->CacheClearE( (APTR)offset,len,CACRF_ClearI ); - - result = TARGET_XFER_OK; - } + IExec->CopyMem( (APTR)writebuf,(APTR)offset,len ); + IExec->CacheClearE( (APTR)offset,len,CACRF_ClearI ); } IMMU->SetMemoryAttrs( (APTR)offset,len,currentAttrs ); @@ -736,7 +843,9 @@ ppc_amigaos_nat_target::xfer_partial (enum target_object object,const char *anne *xfered_len = len; - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d tansferfed %s bytes\n"),__func__,__LINE__,pulongest (*xfered_len)).c_str()); + IExec->DebugPrintF ( string_printf (_("[GDB] %s tansferfed %s bytes\n"),__func__,pulongest (*xfered_len)).c_str()); + + return TARGET_XFER_OK; } break; @@ -744,7 +853,7 @@ ppc_amigaos_nat_target::xfer_partial (enum target_object object,const char *anne { IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d tansferfed object library '%s' failed, aka not supported yet\n"),__func__,__LINE__,annex ).c_str()); - result = TARGET_XFER_E_IO; + return TARGET_XFER_E_IO; } break; @@ -760,13 +869,61 @@ ppc_amigaos_nat_target::xfer_partial (enum target_object object,const char *anne with the current_target having no target beneath). */ } - return result; + return TARGET_XFER_E_IO; } void ppc_amigaos_nat_target::attach (const char *args, int from_tty) { IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d args: '%s', from_tty: %d\n"),__func__,__LINE__,args,from_tty ).c_str()); + + if (!args || !*args) + error ("No task name or address specified for attach"); + + /* Try to interpret args as a hex address first, then as a task name */ + struct Task *task = NULL; + char *endptr; + unsigned long addr = strtoul (args, &endptr, 0); + if (*endptr == '\0' && addr != 0) + { + /* Numeric address — use directly as task pointer */ + task = (struct Task *)addr; + } + else + { + /* Try to find task by name */ + IExec->Forbid (); + task = IExec->FindTask (args); + IExec->Permit (); + } + + if (!task) + error ("Cannot find task '%s'", args); + + /* Suspend the task before installing the debug hook */ + IExec->SuspendTask (task, 0); + + amigaos_debug_hook_data.current_process = (struct Process *)task; + + /* Install debug hook */ + IDebug->AddDebugHook (task, amigaos_debug_hook); + + /* Set up GDB inferior tracking */ + inferior *inf = current_inferior (); + inferior_ptid = ptid_t ((int)task); + inferior_appeared (inf, (int)task); + + inf->unpush_target (this); + if (!inf->target_is_pushed (this)) + inf->push_target (this); + + thread_info *thr = add_thread (this, inferior_ptid); + switch_to_thread (thr); + + if (from_tty) + gdb_printf ("Attached to task %p ('%s')\n", task, task->tc_Node.ln_Name ? task->tc_Node.ln_Name : "unknown"); + + IExec->DebugPrintF("[GDB] %s attached to task %p ('%s')\n", __func__, task, task->tc_Node.ln_Name); } void @@ -801,7 +958,7 @@ ppc_amigaos_relocate_sections (const char *exec_file,BPTR exec_seglist) if( address ) { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d On symfile_object relocated %d section '%s' from 0x%08lx to %p, size %ld, old offset: 0x%s\n"),__func__,__LINE__,section->index,section->name,section->vma,address,section->size,phex ( osect->addr(), sizeof (osect->addr()))).c_str()); + IExec->DebugPrintF ( string_printf (_("[GDB] On symfile_object relocated %d section '%s' from 0x%08lx to %p, size %ld, old offset: 0x%s\n"),section->index,section->name,section->vma,address,section->size,phex ( osect->addr(), sizeof (osect->addr()))).c_str()); offsets[ osect_idx ] = (CORE_ADDR)address - osect->addr(); } @@ -985,24 +1142,28 @@ ULONG amigaos_debug_callback (struct Hook *hook, struct Task *currentTask,struct IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Task: %p ('%s'),Exception ooccured (DBHMT_EXCEPTION)\n"),__func__,__LINE__,currentTask,currentTask->tc_Node.ln_Name ).c_str()); struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + if (!message) + return 0; /* Pool exhausted — resume execution, cannot report */ + message->flags = 0; - message->signal = trap_to_signal( dbgmsg->message.context,message->flags ); - + message->signal = trap_to_signal( dbgmsg->message.context, message->flags ); + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d debug hook sending message: %p\n"),__func__,__LINE__,message ).c_str()); IExec->PutMsg (data->debugger_port,(struct Message *)message); - return 1; // Suspend execution + return 1; /* Suspend execution */ } case DBHMT_ADDTASK: { IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Task: %p ('%s'), (DBHMT_ADDTASK), Task added\n"),__func__,__LINE__,currentTask,currentTask->tc_Node.ln_Name ).c_str()); - struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + if (!message) break; message->flags = DM_FLAGS_TASK_ATTACHED; message->signal = -1; - - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d debug hook sending message: %p\n"),__func__,__LINE__,message ).c_str()); + + IExec->DebugPrintF ("[GDB] debug hook sending message: %p\n",message ); IExec->PutMsg (data->debugger_port,(struct Message *)message); @@ -1013,6 +1174,7 @@ ULONG amigaos_debug_callback (struct Hook *hook, struct Task *currentTask,struct IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Task: %p ('%s'), (DBHMT_REMTASK), Task removed\n"),__func__,__LINE__,currentTask,currentTask->tc_Node.ln_Name ).c_str()); struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + if (!message) break; message->flags = DM_FLAGS_TASK_TERMINATED; message->signal = -1; @@ -1027,10 +1189,11 @@ ULONG amigaos_debug_callback (struct Hook *hook, struct Task *currentTask,struct IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Task: %p ('%s'), (DBHMT_OPENLIB), Task opened library '%s'\n"),__func__,__LINE__,currentTask,currentTask->tc_Node.ln_Name,(char*)dbgmsg->message.library->lib_IdString ).c_str()); struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + if (!message) break; message->flags = DM_FLAGS_TASK_OPENLIB; message->signal = -1; message->library = dbgmsg->message.library; - + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d debug hook sending message: %p\n"),__func__,__LINE__,message ).c_str()); IExec->PutMsg (data->debugger_port,(struct Message *)message); @@ -1041,7 +1204,8 @@ ULONG amigaos_debug_callback (struct Hook *hook, struct Task *currentTask,struct { IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Task: %p ('%s'), (DBHMT_CLOSELIB), Task closed library '%s'\n"),__func__,__LINE__,currentTask,currentTask->tc_Node.ln_Name,(char*)dbgmsg->message.library->lib_IdString ).c_str()); - struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + struct debugger_message *message = ppc_amigaos_nat_target->alloc_message ((struct Process *)currentTask); + if (!message) break; message->flags = DM_FLAGS_TASK_CLOSELIB; message->signal = -1; message->library = dbgmsg->message.library; @@ -1071,6 +1235,9 @@ ULONG amigaos_debug_callback (struct Hook *hook, struct Task *currentTask,struct return 0; // Resume execution } +/* Map AmigaOS SDK trap numbers (from ExceptionContext.Traptype) + to GDB signal numbers. These use the TRAPNUM_* values from + exec/interrupts.h, NOT raw PPC vector offsets. */ static int trap_to_signal(struct ExceptionContext *context, uint32 flags) { @@ -1078,63 +1245,60 @@ trap_to_signal(struct ExceptionContext *context, uint32 flags) if (!context || (flags & DM_FLAGS_TASK_TERMINATED)) { IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return GDB_SIGNAL_QUIT )\n"),__func__,__LINE__ ).c_str()); - + return GDB_SIGNAL_QUIT; } - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d traptype: 0x%lx\n"),__func__,__LINE__,context->Traptype ).c_str()); + IExec->DebugPrintF( "[GDB] traptype: 0x%08lx\n",context->Traptype ); switch (context->Traptype) { - case TRAP_MCE: - case TRAP_DSI: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_SEGV )\n"),__func__,__LINE__ ).c_str()); + case TRAP_BUS_ERROR: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_SEGV ) - bus error/machine check\n"),__func__,__LINE__ ).c_str()); return GDB_SIGNAL_SEGV; - case TRAP_ISI: - case TRAP_ALIGN: - IExec->DebugPrintF ( string_printf (_("[GDB] R%s@%d eturn ( GDB_SIGNAL_BUS )\n"),__func__,__LINE__ ).c_str()); + case TRAP_DATA_SEGMENT: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_SEGV ) - data segment violation\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_SEGV; + case TRAP_INST_SEGMENT: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_BUS ) - instruction segment violation\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_BUS; + case TRAP_ALIGNMENT: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_BUS ) - alignment\n"),__func__,__LINE__ ).c_str()); return GDB_SIGNAL_BUS; - case TRAP_EXTERN: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_INT )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_INT; - case TRAP_PROG: + case TRAP_ILLEGAL_INSTRUCTION: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ILL ) - illegal instruction\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_ILL; + case TRAP_PRIVILEGE_VIOLATION: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ILL ) - privilege violation\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_ILL; + case TRAP_TRAP: + /* Trap instruction — this is how software breakpoints work */ if (context->msr & EXC_FPE) { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_FPE )\n"),__func__,__LINE__ ).c_str()); + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_FPE ) - trap with FPE\\n"),__func__,__LINE__ ).c_str()); return GDB_SIGNAL_FPE; } - else if (context->msr & EXC_ILLEGAL) { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ILL )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_ILL; - } - else if (context->msr & EXC_PRIV) { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ILL )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_ILL; - } - else { - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_TRAP; - } + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP ) - breakpoint/trap\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_TRAP; case TRAP_FPU: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_FPE )\n"),__func__,__LINE__ ).c_str()); + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_FPE ) - FPU exception\n"),__func__,__LINE__ ).c_str()); return GDB_SIGNAL_FPE; - case TRAP_DEC: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ALRM )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_ALRM; - case TRAP_RESERVEDA: - case TRAP_RESERVEDB: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ILL )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_ILL; - case TRAP_SYSCALL: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_CHLD )\n"),__func__,__LINE__ ).c_str()); - return GDB_SIGNAL_CHLD; - case TRAP_TRACEI: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP )\n"),__func__,__LINE__ ).c_str()); + case TRAP_TRACE: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP ) - single step trace\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_TRAP; + case TRAP_DATA_BREAKPOINT: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP ) - data breakpoint (DABR)\n"),__func__,__LINE__ ).c_str()); return GDB_SIGNAL_TRAP; - case TRAP_FPA: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_FPE )\n"),__func__,__LINE__ ).c_str()); + case TRAP_INST_BREAKPOINT: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP ) - instruction breakpoint\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_TRAP; + case TRAP_ALTIVEC_ASSIST: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_FPE ) - AltiVec assist\n"),__func__,__LINE__ ).c_str()); return GDB_SIGNAL_FPE; + case TRAP_RESERVED1: + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_ILL ) - reserved trap\n"),__func__,__LINE__ ).c_str()); + return GDB_SIGNAL_ILL; default: - IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( -1 )\n"),__func__,__LINE__ ).c_str()); - return -1; + IExec->DebugPrintF ( string_printf (_("[GDB] %s@%d Return ( GDB_SIGNAL_TRAP ) - Unknown traptype 0x%08lx\n"),__func__,__LINE__,context->Traptype ).c_str()); + return GDB_SIGNAL_TRAP; } } \ No newline at end of file diff --git a/gdb/ppc-amigaos-nat.h b/gdb/ppc-amigaos-nat.h index e0796f44cf4d..a58b28ff1da7 100644 --- a/gdb/ppc-amigaos-nat.h +++ b/gdb/ppc-amigaos-nat.h @@ -24,33 +24,26 @@ #define PPC_AMIGAOS_SIZEOF_VRREGSET 532 -// Chapter Interrupt Reference union from different ppc32 cpus -#define TRAP_RESET 0x0100 /* System reset */ -#define TRAP_MCE 0x0200 /* Machine check */ -#define TRAP_DSI 0x0300 /* Data storage */ -#define TRAP_DSEGI 0x0380 /* Data segment (Book III v2.01) */ -#define TRAP_ISI 0x0400 /* Instruction storage */ -#define TRAP_ISEGI 0x0480 /* Instruction segment (Book III v2.01)*/ -#define TRAP_EXTERN 0x0500 /* External Interrupt */ -#define TRAP_ALIGN 0x0600 /* Alignment */ -#define TRAP_PROG 0x0700 /* Program */ -#define TRAP_FPU 0x0800 /* FPU Disabled */ -#define TRAP_DEC 0x0900 /* Decrementer */ -#define TRAP_RESERVEDA 0x0a00 /* Reserved (Book III v2.01)*/ -#define TRAP_RESERVEDB 0x0b00 /* Reserved (Book III v2.01)*/ -#define TRAP_SYSCALL 0x0c00 /* System call */ -#define TRAP_TRACEI 0x0d00 /* Trace */ -#define TRAP_FPA 0x0e00 /* Floating-point Assist */ -#define TRAP_PMI 0x0f00 /* Performance monitor (Book III v2.01)*/ -#define TRAP_APU 0x0f20 /* APU Unavailble */ -#define TRAP_PIT 0x1000 /* Programmable-interval timer (PIT) */ -#define TRAP_FIT 0x1010 /* Fixed-interval timer (FIT) */ -#define TRAP_WATCHDOG 0x1020 /* Watch Dog */ -#define TRAP_DTBL 0x1100 /* Data TBL error */ -#define TRAP_ITBL 0x1200 /* Instruction TBL error */ -#define TRAP_DEBUG 0x2000 /* Debug */ +/* AmigaOS SDK trap numbers from exec/interrupts.h (enTrapNumbers). + ExceptionContext.Traptype uses these values, NOT raw PPC vector offsets. */ +#define TRAP_BUS_ERROR 0x01000000 /* Bus error / machine check */ +#define TRAP_DATA_SEGMENT 0x02000000 /* Data segment violation (DSI) */ +#define TRAP_INST_SEGMENT 0x03000000 /* Instruction segment violation (ISI) */ +#define TRAP_ALIGNMENT 0x04000000 /* Alignment violation */ +#define TRAP_ILLEGAL_INSTRUCTION 0x05000000 /* Illegal instruction */ +#define TRAP_PRIVILEGE_VIOLATION 0x06000000 /* Privilege violation */ +#define TRAP_TRAP 0x07000000 /* Trap instruction (breakpoint) */ +#define TRAP_FPU 0x08000000 /* Floating point (disabled/imprecise) */ +#define TRAP_TRACE 0x09000000 /* Single step trace */ +#define TRAP_DATA_BREAKPOINT 0x0a000000 /* Data breakpoint (DABR) */ +#define TRAP_INST_BREAKPOINT 0x0b000000 /* Instruction breakpoint */ +#define TRAP_PERFORMANCE 0x0c000000 /* Performance monitor */ +#define TRAP_THERMAL 0x0d000000 /* Thermal management */ +#define TRAP_RESERVED1 0x0e000000 /* Reserved */ +#define TRAP_ALTIVEC_ASSIST 0x0f000000 /* AltiVec assist */ +#define TRAP_SMI 0x10000000 /* System Management interrupt */ -/* MSR Bits */ +/* MSR Bits for Program exception sub-classification */ #define MSR_TRACE_ENABLE 0x00000400 #define EXC_FPE 0x00100000 #define EXC_ILLEGAL 0x00080000 diff --git a/gdb/ppc-amigaos-tdep.c b/gdb/ppc-amigaos-tdep.c index 4dba12da78e1..d564326e6eb0 100644 --- a/gdb/ppc-amigaos-tdep.c +++ b/gdb/ppc-amigaos-tdep.c @@ -127,20 +127,20 @@ ppc_amigaos_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Canonical paths on this target look like `SYS:Utilities/Clock', for example. */ set_gdbarch_has_amiga_based_file_system (gdbarch, 1); - /* Everything runs in the same address space, but might have a priveta adresse area */ + /* Everything runs in the same address space, but might have a private address area */ set_gdbarch_has_shared_address_space (gdbarch, ppc_amigaos_has_shared_address_space); - // PT_STEP not supported so, need to simulate it, like rs6000-aix + /* PT_STEP not supported, need to simulate it like rs6000-aix */ set_gdbarch_software_single_step (gdbarch, ppc_amigaos_software_single_step); /* Displaced stepping is currently not supported in combination with - software single-stepping. These override the values set by - rs6000_gdbarch_init. */ + software single-stepping. These override the values set by + rs6000_gdbarch_init. */ set_gdbarch_displaced_step_copy_insn (gdbarch, NULL); set_gdbarch_displaced_step_fixup (gdbarch, NULL); set_gdbarch_displaced_step_prepare (gdbarch, NULL); set_gdbarch_displaced_step_finish (gdbarch, NULL); - // Traget bfd name, seems to be only needed for message/debug output + /* Target bfd name for message/debug output */ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc-amigaos"); } diff --git a/gdb/source.c b/gdb/source.c index fe3c60d2489f..681ed6109b4b 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -836,7 +836,7 @@ openp (const char *path, openp_flags opts, const char *string, #else path = "."; #endif - + mode |= O_BINARY; if ((opts & OPF_TRY_CWD_FIRST) || IS_ABSOLUTE_PATH (string)) diff --git a/gdbsupport/pathstuff.cc b/gdbsupport/pathstuff.cc index 3439d6f38f72..b8e204b99beb 100644 --- a/gdbsupport/pathstuff.cc +++ b/gdbsupport/pathstuff.cc @@ -71,6 +71,13 @@ gdb_realpath (const char *filename) if (len > 0 && len < MAX_PATH) return make_unique_xstrdup (buf); } +#elif defined (__amigaos4__) + /* AmigaOS realpath() resolves assigns and volume names (e.g. T: -> + "RAM Disk:T/", SYS: -> "AmigaOS:"), which can produce paths that + fail to reopen later via BFD's file cache (spaces in volume names, + inconsistent resolution of assigns). Return the path as-is to + preserve the original working path that was successfully opened. */ + return make_unique_xstrdup (filename); #else { char *rp = canonicalize_file_name (filename); diff --git a/libiberty/pex-amigaos.c b/libiberty/pex-amigaos.c index c0cda0873976..0c61a108764c 100644 --- a/libiberty/pex-amigaos.c +++ b/libiberty/pex-amigaos.c @@ -47,13 +47,13 @@ extern int errno; #endif static int pex_amiga_open_read (struct pex_obj *, const char *, int); -static int pex_amiga_open_write (struct pex_obj *, const char *, int, int); +static int pex_amiga_open_write (struct pex_obj *, const char *, int); static pid_t pex_amiga_exec_child (struct pex_obj *, int, const char *, char * const *, char * const *, int, int, int, int, const char **, int *); static int pex_amiga_close (struct pex_obj *, int); -static pid_t pex_amiga_wait (struct pex_obj *, pid_t, int *, struct pex_time *, +static int pex_amiga_wait (struct pex_obj *, long, int *, struct pex_time *, int, const char **, int *); static FILE *pex_amiga_fdopenr (struct pex_obj *, int, int); static FILE *pex_amiga_fdopenw (struct pex_obj *, int, int); @@ -96,7 +96,7 @@ pex_amiga_open_read (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, static int pex_amiga_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, - int binary ATTRIBUTE_UNUSED, int append ATTRIBUTE_UNUSED) + int binary ATTRIBUTE_UNUSED) { /* Note that we can't use O_EXCL here because gcc may have already created the temporary file via make_temp_file. */ @@ -307,8 +307,8 @@ pex_amiga_fdopenw (struct pex_obj *obj ATTRIBUTE_UNUSED, int fd, has already completed, and we just need to return the exit status. */ -static pid_t -pex_amiga_wait (struct pex_obj *obj, pid_t pid, int *status, +static int +pex_amiga_wait (struct pex_obj *obj, long pid, int *status, struct pex_time *time, int done ATTRIBUTE_UNUSED, const char **errmsg ATTRIBUTE_UNUSED, int *err ATTRIBUTE_UNUSED)