static enum target_xfer_status record_btrace_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) { struct target_ops *t; /* Filter out requests that don't make sense during replay. */ if (!record_btrace_allow_memory_access && record_btrace_is_replaying (ops)) { switch (object) { case TARGET_OBJECT_MEMORY: { struct target_section *section; /* We do not allow writing memory in general. */ if (writebuf != NULL) { *xfered_len = len; return TARGET_XFER_UNAVAILABLE; } /* We allow reading readonly memory. */ section = target_section_by_addr (ops, offset); if (section != NULL) { /* Check if the section we found is readonly. */ if ((bfd_get_section_flags (section->the_bfd_section->owner, section->the_bfd_section) & SEC_READONLY) != 0) { /* Truncate the request to fit into this section. */ len = min (len, section->endaddr - offset); break; } } *xfered_len = len; return TARGET_XFER_UNAVAILABLE; } } } /* Forward the request. */ for (ops = ops->beneath; ops != NULL; ops = ops->beneath) if (ops->to_xfer_partial != NULL) return ops->to_xfer_partial (ops, object, annex, readbuf, writebuf, offset, len, xfered_len); *xfered_len = len; return TARGET_XFER_UNAVAILABLE; }
static CORE_ADDR ppc64_fbsd_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, struct target_ops *targ) { struct section_table *s = target_section_by_addr (targ, addr); /* Check if ADDR points to a function descriptor. */ if (s && strcmp (s->the_bfd_section->name, ".opd") == 0) return get_target_memory_unsigned (targ, addr, 8); return addr; }
CORE_ADDR ppc64_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, struct target_ops *targ) { enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); struct target_section *s = target_section_by_addr (targ, addr); /* Check if ADDR points to a function descriptor. */ if (s && strcmp (s->the_bfd_section->name, ".opd") == 0) { /* There may be relocations that need to be applied to the .opd section. Unfortunately, this function may be called at a time where these relocations have not yet been performed -- this can happen for example shortly after a library has been loaded with dlopen, but ld.so has not yet applied the relocations. To cope with both the case where the relocation has been applied, and the case where it has not yet been applied, we do *not* read the (maybe) relocated value from target memory, but we instead read the non-relocated value from the BFD, and apply the relocation offset manually. This makes the assumption that all .opd entries are always relocated by the same offset the section itself was relocated. This should always be the case for GNU/Linux executables and shared libraries. Note that other kind of object files (e.g. those added via add-symbol-files) will currently never end up here anyway, as this function accesses *target* sections only; only the main exec and shared libraries are ever added to the target. */ gdb_byte buf[8]; int res; res = bfd_get_section_contents (s->the_bfd_section->owner, s->the_bfd_section, &buf, addr - s->addr, 8); if (res != 0) return extract_unsigned_integer (buf, 8, byte_order) - bfd_section_vma (s->bfd, s->the_bfd_section) + s->addr; } return addr; }
LONGEST target_bfd_xfer_partial (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, const gdb_byte *writebuf, ULONGEST offset, LONGEST len) { switch (object) { case TARGET_OBJECT_MEMORY: { struct section_table *s = target_section_by_addr (ops, offset); if (s == NULL) return -1; /* If the length extends beyond the section, truncate it. Be careful to not suffer from overflow (wish S contained a length). */ if ((offset - s->addr + len) > (s->endaddr - s->addr)) len = (s->endaddr - s->addr) - (offset - s->addr); if (readbuf != NULL && !bfd_get_section_contents (s->bfd, s->the_bfd_section, readbuf, offset - s->addr, len)) return -1; #if 1 if (writebuf != NULL) return -1; #else /* FIXME: cagney/2003-10-31: The BFD interface doesn't yet take a const buffer. */ if (writebuf != NULL && !bfd_set_section_contents (s->bfd, s->the_bfd_section, writebuf, offset - s->addr, len)) return -1; #endif return len; } default: return -1; } }
static CORE_ADDR ppc_linux_convert_from_func_ptr_addr (struct gdbarch *gdbarch, CORE_ADDR addr, struct target_ops *targ) { struct gdbarch_tdep *tdep; struct section_table *s = target_section_by_addr (targ, addr); char *sect_name = NULL; if (!s) return addr; tdep = gdbarch_tdep (gdbarch); switch (tdep->wordsize) { case 4: sect_name = ".plt"; break; case 8: sect_name = ".opd"; break; default: internal_error (__FILE__, __LINE__, _("failed internal consistency check")); } /* Check if ADDR points to a function descriptor. */ /* NOTE: this depends on the coincidence that the address of a functions entry point is contained in the first word of its function descriptor for both PPC-64 and for PPC-32 with secure PLTs. */ if ((strcmp (s->the_bfd_section->name, sect_name) == 0) && s->the_bfd_section->flags & SEC_DATA) return get_target_memory_unsigned (targ, addr, tdep->wordsize); return addr; }