[PATCH] Add OSE operating system support [1/5] ose core format support of bfd
Hui Zhu
hui_zhu@mentor.com
Tue Mar 5 09:58:00 GMT 2013
Hi,
OSE's core file format is different compared to Linux, so there is patch for bfd to handle this format.
Thanks,
Hui
2013-03-05 Luis Machado <lgustavo@codesourcery.com>
* Makefile.am (BFD32_BACKENDS): Add ose-core.lo.
(BFD32_BACKENDS_CFILES): Add ose-core.c.
* bfd-in2.h (bfd): Add ose_core_data.
* bfd.c (bfd): Ditto.
* config.bfd: Add ose_core_big_vec and ose_core_little_vec.
* configure: Ditto.
* configure.in: Ditto.
* ose-core.c: New.
* targets.c: Add ose_core_big_vec and ose_core_little_vec.
-------------- next part --------------
--- a/bfd/Makefile.am
+++ b/bfd/Makefile.am
@@ -445,7 +445,8 @@ BFD32_BACKENDS = \
xcofflink.lo \
xsym.lo \
xtensa-isa.lo \
- xtensa-modules.lo
+ xtensa-modules.lo \
+ ose-core.lo
BFD32_BACKENDS_CFILES = \
aout-adobe.c \
@@ -634,7 +635,8 @@ BFD32_BACKENDS_CFILES = \
xcofflink.c \
xsym.c \
xtensa-isa.c \
- xtensa-modules.c
+ xtensa-modules.c \
+ ose-core.c
# The .o files needed by all of the 64 bit vectors that are configured into
# target_vector in targets.c if configured with --enable-targets=all
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6041,6 +6041,7 @@ struct bfd
struct lynx_core_struct *lynx_core_data;
struct osf_core_struct *osf_core_data;
struct cisco_core_struct *cisco_core_data;
+ struct ose_core_struct *ose_core_data;
struct versados_data_struct *versados_data;
struct netbsd_core_struct *netbsd_core_data;
struct mach_o_data_struct *mach_o_data;
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -256,6 +256,7 @@ CODE_FRAGMENT
. struct lynx_core_struct *lynx_core_data;
. struct osf_core_struct *osf_core_data;
. struct cisco_core_struct *cisco_core_data;
+. struct ose_core_struct *ose_core_data;
. struct versados_data_struct *versados_data;
. struct netbsd_core_struct *netbsd_core_data;
. struct mach_o_data_struct *mach_o_data;
--- a/bfd/config.bfd
+++ b/bfd/config.bfd
@@ -1255,9 +1255,9 @@ case "${targ}" in
;;
powerpc-*-*bsd* | powerpc-*-elf* | powerpc-*-sysv4* | powerpc-*-eabi* | \
powerpc-*-solaris2* | powerpc-*-linux-* | powerpc-*-rtems* | \
- powerpc-*-chorus*)
+ powerpc-*-chorus* | powerpc-*-ose)
targ_defvec=bfd_elf32_powerpc_vec
- targ_selvecs="rs6000coff_vec bfd_elf32_powerpcle_vec ppcboot_vec"
+ targ_selvecs="rs6000coff_vec bfd_elf32_powerpcle_vec ppcboot_vec ose_core_big_vec ose_core_little_vec"
targ64_selvecs="bfd_elf64_powerpc_vec bfd_elf64_powerpcle_vec"
;;
powerpc-*-kaos*)
--- a/bfd/configure
+++ b/bfd/configure
@@ -15528,6 +15528,9 @@ do
cisco_core_big_vec) tb="$tb cisco-core.lo" ;;
cisco_core_little_vec) tb="$tb cisco-core.lo" ;;
+ ose_core_big_vec) tb="$tb ose-core.lo" ;;
+ ose_core_little_vec) tb="$tb ose-core.lo" ;;
+
"") ;;
*) as_fn_error "*** unknown target vector $vec" "$LINENO" 5 ;;
esac
--- a/bfd/configure.in
+++ b/bfd/configure.in
@@ -1025,6 +1025,9 @@ do
cisco_core_big_vec) tb="$tb cisco-core.lo" ;;
cisco_core_little_vec) tb="$tb cisco-core.lo" ;;
+ ose_core_big_vec) tb="$tb ose-core.lo" ;;
+ ose_core_little_vec) tb="$tb ose-core.lo" ;;
+
"") ;;
*) AC_MSG_ERROR(*** unknown target vector $vec) ;;
esac
--- /dev/null
+++ b/bfd/ose-core.c
@@ -0,0 +1,1940 @@
+/* BFD back-end for OSE crash dumps.
+ Copyright 2012 Free Software Foundation, Inc.
+
+ This file is part of BFD, the Binary File Descriptor library.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "sysdep.h"
+#include "bfd.h"
+#include "libbfd.h"
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+
+#ifdef HAVE_ZLIB_H
+#include <zlib.h>
+#endif
+
+static int debug_ose_core;
+
+static void
+ose_debug (const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!debug_ose_core)
+ return;
+
+ va_start (ap, fmt);
+ vfprintf (stderr, fmt, ap);
+ va_end (ap);
+}
+
+struct ose_core_struct
+{
+ /* FIXME: we aren't setting these anywhere yet. */
+ int sig;
+ int bid;
+};
+
+/* Begin generic IFF reader. This is based on the iff.h and iffr.c
+ files of the public domain generic IFF reader for the Amiga. See
+ <http://www.martinreddy.net/gfx/2d/IFF.txt>. Copies of this code
+ are found in the Fish disks.
+
+ The original IFF.H file contains the following header: */
+
+/*--- begin original header --- */
+
+/*----------------------------------------------------------------------*/
+/* IFF.H defs for IFF-85 Interchange Format Files. 10/8/85 */
+/* */
+/* By Jerry Morrison and Steve Shaw, Electronic Arts. */
+/* This software is in the public domain. */
+/*----------------------------------------------------------------------*/
+
+/*--- end original header --- */
+
+/* This version has been bfd-ized, formatting fixed, function names
+ adjusted to be library compatible (it's not like the original is
+ maintained anyway), some unnecessary functions were removed, and a
+ few bugs fixed too. */
+
+/* Status code result from an IFF procedure. int, because it must be
+ type compatible with ID for iff_get_chunk_header. */
+
+typedef int IFFP;
+
+/* Note that the error codes below are not legal IDs. */
+
+/* Keep going... */
+#define IFF_OKAY 0L
+
+/* As if there was a chunk at end of group. */
+#define END_MARK (-1L)
+
+/* A client procedure returns this when it has READ enough. It means
+ return through all levels. File is Okay. */
+#define IFF_DONE (-2L)
+
+/* The OS returned some error. Ask the OS what it was. */
+#define OS_ERROR (-3L)
+
+/* Not an IFF file. */
+#define NOT_IFF (-4L)
+
+/* Tried to open file, DOS didn't find it. */
+#define NO_FILE (-5L)
+
+/* Client made invalid request, for instance, asking for more bytes
+ than existed in chunk.*/
+#define CLIENT_ERROR (-6L)
+
+/* A client read proc complains about FORM semantics; e.g. valid IFF,
+ but missing a required chunk. */
+#define BAD_FORM (-7L)
+
+/* Client asked to iff_read_bytes more bytes than left in the chunk.
+ Could be client bug or bad form. */
+#define SHORT_CHUNK (-8L)
+
+/* mal-formed IFF file. */
+#define BAD_IFF (-9L)
+
+#define LAST_ERROR BAD_IFF
+
+/* ---------- ID -------------------------------------------------------*/
+
+/* An ID is four printable ASCII chars but stored as a int for
+ efficient copy & compare. */
+typedef int ID;
+
+/* Four-character IDentifier builder. */
+#define MakeID(a,b,c,d) (((long)(a))<<24L | ((long)(b))<<16L | (c)<<8 | (d))
+
+/* Standard group IDs. A chunk with one of these IDs contains a
+ SubTypeID followed by zero or more chunks. */
+#define FORM MakeID ('F','O','R','M')
+#define PROP MakeID ('P','R','O','P')
+#define LIST MakeID ('L','I','S','T')
+#define CAT MakeID ('C','A','T',' ')
+#define FILLER MakeID (' ',' ',' ',' ')
+
+/* The IDs "FOR1".."FOR9", "LIS1".."LIS9", & "CAT1".."CAT9" are
+ reserved for future standardization. */
+
+/* Pseudo-ID used internally by the chunk reader, meaning no current
+ chunk. */
+#define NULL_CHUNK 0L
+
+/* ---------- Chunk ---------------------------------------------------- */
+
+/* All chunks start with a type ID and a count of the data bytes that
+ follow -- the chunk's "logical size" or "data size". If that
+ number is odd, a 0 pad byte is written, too. */
+
+typedef struct
+{
+ ID ID;
+ int size;
+} iff_chunk_header;
+
+/* Need to know whether a value is odd so can word-align. */
+#define IS_ODD(a) ((a) & 1)
+
+/* ---------- IFF Reader -----------------------------------------------*/
+
+struct _iff_group_context;
+
+/* Routines to support a stream-oriented IFF file reader.
+
+ These routines handle lots of details like error checking and
+ skipping over padding. They're also careful not to read past any
+ containing context.
+
+ These routines ASSUME they're the only ones reading from the file.
+ Client should check IFFP error codes. Don't press on after an
+ error! These routines try to have no side effects in the error
+ case, except partial I/O is sometimes unavoidable.
+
+ All of these routines may return OS_ERROR. In that case, ask the OS
+ for the specific error code.
+
+ The overall scheme for the low level chunk reader is to open a
+ "group read context" with iff_open_read or iff_open_read_group,
+ read the chunks with iff_get_chunk_header (and its kin) and
+ iff_read_bytes, and close the context with iff_close_read_group.
+
+ The overall scheme for reading an IFF file is to use iff_read,
+ iff_read_list, and iff_read_cat to scan the file. See those procedures,
+ and ClientProc (below). */
+
+
+/* Client passes ptrs to procedures of this type to iff_read which
+ call them back to handle LISTs, FORMs, CATs, and PROPs.
+
+ Use the iff_group_context ptr when calling reader routines like
+ iff_get_chunk_header. Look inside the iff_group_context ptr for
+ your iff_client_frame ptr. You'll want to type cast it into a ptr
+ to your containing struct to get your private contextual data
+ (stacked property settings). See below. */
+
+typedef IFFP iff_group_client_proc (struct _iff_group_context *);
+
+/* Client's context for reading an IFF file or a group.
+
+ Client should actually make this the first component of a larger
+ struct (it's personal stack "frame") that has a field to store each
+ "interesting" property encountered.
+
+ Either initialize each such field to a global default or keep a
+ boolean indicating if you've read a property chunk into that field.
+
+ Your get_list and get_form procs should allocate a new "frame" and
+ copy the parent frame's contents. The get_prop procedure should
+ store into the frame allocated by get_list for the containing
+ LIST. */
+
+typedef struct _iff_client_frame
+{
+ iff_group_client_proc *get_list;
+ iff_group_client_proc *get_prop;
+ iff_group_client_proc *get_form;
+ iff_group_client_proc *get_cat;
+ /* Client's own data follows; place to stack property settings. */
+} iff_client_frame;
+
+/* Our context for reading a group chunk. */
+typedef struct _iff_group_context
+{
+ /* Containing group; NULL => whole file. */
+ struct _iff_group_context *parent;
+
+ /* Reader data & client's context state. */
+ iff_client_frame *client_frame;
+
+ /* The bfd. */
+ bfd *abfd;
+
+ /* The context's logical file position. */
+ int position;
+
+ /* File-absolute context bound. */
+ int bound;
+
+ /* Current chunk header. See also Pseudo-IDs, above. */
+ iff_chunk_header ck_hdr;
+
+ /* Group's subtype ID when reading. */
+ ID subtype;
+
+ /* Number of bytes read of current chunk's data. */
+ int bytesSoFar;
+} iff_group_context;
+
+/* Computes the number of bytes not yet read from the current chunk,
+ given a group read context GC. */
+#define CHUNK_MORE_BYTES(gc) ((gc)->ck_hdr.size - (gc)->bytesSoFar)
+
+
+/* Low Level IFF Chunk Reader. */
+
+/* Given an open file, open a read context spanning the whole file.
+ This is normally only called by iff_read. This sets
+ new->client_frame = client_frame. Assumes the context is allocated
+ by the caller but not initialized. Assumes the caller doesn't
+ deallocate the context before calling iff_close_read_group. Returns NOT_IFF
+ error if the file is too short for even a chunk header. */
+static IFFP iff_open_read (bfd *file, iff_group_context *, iff_client_frame *);
+
+/* Open the remainder of the current chunk as a group read context.
+ This will be called just after the group's subtype ID has been read
+ (automatically by iff_get_chunk_header for LIST, FORM, PROP, and CAT) so the
+ remainder is a sequence of chunks.
+
+ This sets new->client_frame = parent->client_frame. The caller should
+ re-point it at a new client_frame if opening a LIST context so it'll
+ have a "stack frame" to store PROPs for the LIST. (It's usually
+ convenient to also allocate a new Frame when you encounter FORM of
+ the right type.)
+
+ NEW is allocated by the caller but not initialized. The caller
+ does not deallocate the context or access the parent context before
+ calling iff_close_read_group.
+
+ Returns a BAD_IFF error if the context's end is odd or extends past
+ the parent. */
+static IFFP iff_open_read_group (iff_group_context *parent,
+ iff_group_context *new);
+
+/* Close a group read context, updating its parent context. After
+ calling this, the old context may be deallocated and the parent
+ context can be accessed again. It's okay to call this particular
+ procedure after an error has occurred reading the group. This
+ always returns IFF_OKAY. */
+static IFFP iff_close_read_group (iff_group_context *old);
+
+/* Skip any remaining bytes of the previous chunk and any padding,
+ then read the next chunk header into context.ck_hdr.
+
+ If the chunk ID is LIST, FORM, CAT, or PROP, this automatically
+ reads the subtype ID into context->subtype. Caller should dispatch
+ on the chunk's ID (and subtype) to an appropriate handler.
+
+ Returns context.ck_hdr.ID (the ID of the new chunk header); END_MARK
+ if there are no more chunks in this context; NOT_IFF if the top
+ level file chunk isn't a FORM, LIST, or CAT; or BAD_IFF if
+ malformed chunk, e.g., chunk's size is negative or too big for
+ containing context, chunk ID isn't positive, or we hit end-of-file.
+
+ See also iff_get_form_chunk_header, below. */
+
+static ID iff_get_chunk_header (iff_group_context *ctx);
+
+/* Read NBYTES number of data bytes of current chunk into BUFFER.
+ (Use OpenGroup, etc. instead to read the contents of a group
+ chunk.) You can call this several times to read the data
+ piecemeal.
+
+ Returns CLIENT_ERROR if NBYTES < 0. SHORT_CHUNK if NBYTES >
+ CHUNK_MORE_BYTES(context) which could be due to a client bug or a
+ chunk that's shorter than it ought to be (bad form). On either
+ CLIENT_ERROR or SHORT_CHUNK, iff_read_bytes won't read any bytes. */
+
+static IFFP iff_read_bytes (iff_group_context *ctx,
+ bfd_byte *buffer, int nbytes);
+
+/* IFF File Reader. */
+
+/* This is a noop iff_group_client_proc that you can use for a
+ get_list, get_form, get_prop, or get_cat procedure that just skips
+ the group. A simple reader might just implement get_form, store
+ &iff_read_cat in the get_cat field of client_frame, and use
+ &iff_skip_group for the get_list and get_prop procs. */
+
+static IFFP iff_skip_group (iff_group_context *);
+
+/* IFF file reader.
+
+ Given an open file, allocate a group context and use it to read the
+ FORM, LIST, or CAT and it's contents. The idea is to parse the
+ file's contents, and for each FORM, LIST, CAT, or PROP encountered,
+ call the get_form, get_list, get_cat, or get_prop procedure in
+ client_frame, passing the iff_group_context ptr.
+
+ This is achieved with the aid of iff_read_list (which your get_list
+ should call) and iff_read_cat (which your get_cat should call, if you
+ don't just use &iff_read_cat for your get_cat). If you want to handle
+ FORMs, LISTs, and CATs nested within FORMs, the get_form procedure
+ must dispatch to get_form, get_list, and get_cat.
+
+ Normal return is IFF_OKAY (if whole file scanned) or IFF_DONE (if a
+ client proc said "done" first).
+
+ See the skeletal get_list, get_form, get_cat, and get_prop
+ procedures. */
+static IFFP iff_read (bfd *file, iff_client_frame *client_frame);
+
+/* IFF LIST reader.
+
+ Your "get_list" procedure should allocate a iff_client_frame, copy the
+ parent's iff_client_frame, and then call this procedure to do all the
+ work.
+
+ Normal return is IFF_OKAY (if whole LIST scanned) or IFF_DONE (if a
+ client proc said "done" first).
+
+ Returns BAD_IFF error if a PROP appears after a non-PROP. */
+static IFFP iff_read_list (iff_group_context *parent,
+ iff_client_frame *client_frame);
+
+#if 0
+/* IFF CAT reader. Most clients can simply use this to read their
+ CATs. If you must do extra setup work, put a ptr to your get_cat
+ procedure in the client_frame, and have that procedure call iff_read_cat
+ to do the detail work.
+
+ Normal return is IFF_OKAY (if whole CAT scanned) or IFF_DONE (if a
+ client proc said "done" first).
+
+ Returns BAD_IFF error if a PROP appears in the CAT. */
+static IFFP iff_read_cat (iff_group_context *parent);
+#endif
+
+/* Call iff_get_form_chunk_header instead of iff_get_chunk_header to
+ read each chunk inside a FORM. It just calls iff_get_chunk_header
+ and returns BAD_IFF if it gets a PROP chunk. */
+static ID iff_get_form_chunk_header (iff_group_context *ctx);
+
+/* The following code is based on IFFR.C from the public domain IFF
+ reader. Its header contains: */
+
+/*--- begin original header --- */
+
+/*----------------------------------------------------------------------*
+ * IFFR.C Support routines for reading IFF-85 files. 11/15/85
+ * (IFF is Interchange Format File.)
+ *
+ * By Jerry Morrison and Steve Shaw, Electronic Arts.
+ * This software is in the public domain.
+ *
+ * This version for the Commodore-Amiga computer.
+ *----------------------------------------------------------------------*/
+
+/*--- end original header --- */
+
+static IFFP
+iff_open_read (bfd *abfd, iff_group_context *new_ctx,
+ iff_client_frame *client_frame)
+{
+ IFFP iffp = IFF_OKAY;
+
+ /* The "whole file" has no parent. */
+ new_ctx->parent = NULL;
+ new_ctx->client_frame = client_frame;
+ new_ctx->abfd = abfd;
+ new_ctx->position = 0;
+ new_ctx->ck_hdr.ID = new_ctx->subtype = NULL_CHUNK;
+ new_ctx->ck_hdr.size = new_ctx->bytesSoFar = 0;
+
+ /* Set new_ctx->bound. */
+ if (abfd == NULL)
+ return NO_FILE;
+ new_ctx->bound = bfd_get_size (abfd);
+ if (new_ctx->bound < 0)
+ return OS_ERROR;
+
+ if (new_ctx->bound < (long) sizeof (iff_chunk_header))
+ iffp = NOT_IFF;
+
+ return iffp;
+}
+
+static IFFP
+iff_open_read_group (iff_group_context* parent, iff_group_context* new_ctx)
+{
+ IFFP iffp = IFF_OKAY;
+
+ new_ctx->parent = parent;
+ new_ctx->client_frame = parent->client_frame;
+ new_ctx->abfd = parent->abfd;
+ new_ctx->position = parent->position;
+ new_ctx->bound = parent->position + CHUNK_MORE_BYTES (parent);
+ new_ctx->ck_hdr.ID = new_ctx->subtype = NULL_CHUNK;
+ new_ctx->ck_hdr.size = new_ctx->bytesSoFar = 0;
+
+ if (new_ctx->bound > parent->bound || IS_ODD (new_ctx->bound))
+ iffp = BAD_IFF;
+
+ return iffp;
+}
+
+static IFFP
+iff_close_read_group (iff_group_context *context)
+{
+ if (context->parent == NULL)
+ {
+ /* Context for whole file. */
+ }
+ else
+ {
+ int position;
+
+ position = context->position;
+ context->parent->bytesSoFar += position - context->parent->position;
+ context->parent->position = position;
+ }
+
+ return IFF_OKAY;
+}
+
+/* Skip over bytes in a context. Won't go backwards. Updates
+ context->position but not context->bytesSoFar. */
+
+static IFFP
+skip_fwd (iff_group_context *context, int bytes)
+{
+ IFFP iffp = IFF_OKAY;
+
+ if (bytes > 0)
+ {
+ if (-1 == bfd_seek (context->abfd, bytes, SEEK_CUR))
+ iffp = BAD_IFF; /* Ran out of bytes before chunk
+ complete. */
+ else
+ context->position += bytes;
+ }
+
+ return iffp;
+}
+
+static IFFP
+iff_get_chunk_header (iff_group_context *context)
+{
+ IFFP iffp;
+ int remaining;
+
+ /* Skip remainder of previous chunk & padding. */
+ iffp = skip_fwd (context,
+ CHUNK_MORE_BYTES (context) + IS_ODD (context->ck_hdr.size));
+ if (iffp != IFF_OKAY)
+ return iffp;
+
+ /* Set up to read the newtmp header. Until we know it's okay, mark
+ it BAD. */
+ context->ck_hdr.ID = BAD_IFF;
+ context->subtype = NULL_CHUNK;
+ context->bytesSoFar = 0;
+
+ /* Generate a pseudo-chunk if at end-of-context. */
+ remaining = context->bound - context->position;
+ if (remaining == 0 )
+ {
+ context->ck_hdr.size = 0;
+ context->ck_hdr.ID = END_MARK;
+ }
+ else if ((long) sizeof (iff_chunk_header) > remaining)
+ {
+ /* BAD_IFF if not enough bytes in the context for a
+ iff_chunk_header. */
+ context->ck_hdr.size = remaining;
+ }
+ else
+ {
+ /* Read the chunk header (finally). */
+
+ /* All chunks start with a type ID and a count of the data bytes
+ that follow--the chunk's "logical size" or "data size". If
+ that number is odd, a 0 pad byte is written, too. */
+ char buf[8];
+
+ switch (bfd_bread (buf, 8, context->abfd))
+ {
+ case -1:
+ return (context->ck_hdr.ID = OS_ERROR);
+ case 0:
+ return (context->ck_hdr.ID = BAD_IFF);
+ }
+
+ context->ck_hdr.ID = bfd_getb32 (buf);
+ context->ck_hdr.size = bfd_getb32 (buf + 4);
+
+ /* Check: Top level chunk must be LIST or FORM or CAT. */
+ if (context->parent == NULL
+ && context->ck_hdr.ID != FORM
+ && context->ck_hdr.ID != LIST
+ && context->ck_hdr.ID != CAT)
+ return (context->ck_hdr.ID = NOT_IFF);
+
+ /* Update the context. */
+ context->position += (long) sizeof (iff_chunk_header);
+ remaining -= (long) sizeof (iff_chunk_header);
+
+ if (context->ck_hdr.ID <= 0)
+ {
+ /* Non-positive int values are illegal and used for error
+ codes. We could check for other illegal IDs... */
+ context->ck_hdr.ID = BAD_IFF;
+ }
+ else if (context->ck_hdr.size < 0
+ || context->ck_hdr.size > remaining)
+ {
+ /* Check: size negative or larger than the number of bytes
+ left in context? */
+ context->ck_hdr.size = remaining;
+ context->ck_hdr.ID = BAD_IFF;
+ }
+ else
+ {
+ /* Automatically read the LIST, FORM, PROP, or CAT subtype
+ int. */
+ if (context->ck_hdr.ID == LIST
+ || context->ck_hdr.ID == FORM
+ || context->ck_hdr.ID == PROP
+ || context->ck_hdr.ID == CAT)
+ {
+ uint32_t id;
+
+ iffp = iff_read_bytes (context, (bfd_byte *) &id, 4);
+
+ if (iffp != IFF_OKAY)
+ context->ck_hdr.ID = iffp;
+ else
+ context->subtype = bfd_getb32 (&id);
+ }
+ }
+ }
+
+ return context->ck_hdr.ID;
+}
+
+static IFFP
+iff_read_bytes (iff_group_context *context, bfd_byte *buffer, int nbytes)
+{
+ IFFP iffp = IFF_OKAY;
+
+ if (nbytes < 0)
+ iffp = CLIENT_ERROR;
+ else if (nbytes > CHUNK_MORE_BYTES (context))
+ iffp = SHORT_CHUNK;
+ else if (nbytes > 0)
+ {
+ switch (bfd_bread (buffer, nbytes, context->abfd))
+ {
+ case -1:
+ iffp = OS_ERROR;
+ break;
+ case 0:
+ iffp = BAD_IFF;
+ break;
+ default:
+ context->position += nbytes;
+ context->bytesSoFar += nbytes;
+ break;
+ }
+ }
+
+ return iffp;
+}
+
+static IFFP
+iff_skip_group (iff_group_context* context ATTRIBUTE_UNUSED)
+{
+ /* Nothing to do, thanks to iff_get_chunk_header. */
+ return 0;
+}
+
+static IFFP
+iff_read (bfd *file, iff_client_frame *client_frame)
+{
+ IFFP iffp;
+ iff_group_context context;
+
+ iffp = iff_open_read (file, &context, client_frame);
+ context.client_frame = client_frame;
+
+ if (iffp == IFF_OKAY)
+ {
+ iffp = iff_get_chunk_header (&context);
+
+ if (iffp == FORM)
+ iffp = (*client_frame->get_form) (&context);
+ else if (iffp == LIST)
+ iffp = (*client_frame->get_list) (&context);
+ else if (iffp == CAT)
+ iffp = (*client_frame->get_cat) (&context);
+ }
+ iff_close_read_group (&context);
+
+ if (iffp > 0)
+ iffp = NOT_IFF; /* iff_get_chunk_header should've caught this. */
+ return iffp;
+}
+
+static IFFP
+iff_read_list (iff_group_context *parent, iff_client_frame *client_frame)
+{
+ iff_group_context list_context;
+ IFFP iffp;
+ bfd_boolean prop_ok = TRUE;
+
+ iffp = iff_open_read_group (parent, &list_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+
+ /* One special case test lets us handle CATs as well as LISTs. */
+ if (parent->ck_hdr.ID == CAT)
+ prop_ok = FALSE;
+ else
+ list_context.client_frame = client_frame;
+
+ do
+ {
+ iffp = iff_get_chunk_header (&list_context);
+ if (iffp == PROP)
+ {
+ if (prop_ok)
+ iffp = (*client_frame->get_prop) (&list_context);
+ else
+ iffp = BAD_IFF;
+ }
+ else if (iffp == FORM)
+ iffp = (*client_frame->get_form) (&list_context);
+ else if (iffp == LIST)
+ iffp = (*client_frame->get_list) (&list_context);
+ else if (iffp == CAT)
+ iffp = (*client_frame->get_cat) (&list_context);
+
+ if (list_context.ck_hdr.ID != PROP)
+ prop_ok = FALSE; /* No PROPs allowed after this point. */
+ } while (iffp == IFF_OKAY);
+
+ iff_close_read_group (&list_context);
+
+ /* Only chunk types above are allowed in a LIST/CAT. */
+ if (iffp > 0)
+ iffp = BAD_IFF;
+ return (iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+#if 0
+/* By special arrangement with the iff_read_list implementation, this
+ is trivial. */
+
+static IFFP
+iff_read_cat (iff_group_context *parent)
+{
+ return iff_read_list (parent, parent->client_frame);
+}
+#endif
+
+static int
+iff_get_form_chunk_header (iff_group_context *context)
+{
+ int id;
+
+ id = iff_get_chunk_header (context);
+ if (id == PROP)
+ context->ck_hdr.ID = id = BAD_IFF;
+ return id;
+}
+
+/* End of generic IFF reader. */
+
+
+/* PMD reader. */
+
+typedef uint32_t U32;
+
+#define MONITOR_INTERFACE_REQUEST 39000
+#define MONITOR_CONNECT_REQUEST 39008
+#define MONITOR_GET_PROCESS_INFO_REQUEST 39010
+#define MONITOR_GET_PROCESS_INFO_REPLY 39011
+#define MONITOR_GET_BLOCK_INFO_REQUEST 39014
+#define MONITOR_GET_SEGMENT_INFO_REQUEST 39017
+#define MONITOR_GET_REGISTER_INFO_REQUEST 39121
+#define MONITOR_GET_REGISTERS_REPLY 39106
+
+#define MONITOR_GET_TRACE_REQUEST 39215
+
+#define PM_PROGRAMS_REQUEST 36232
+#define PM_PROGRAM_INFO_REQUEST 36234
+#define PM_LOAD_MODULE_INSTALL_HANDLES_REQUEST 36214
+#define PM_LOAD_MODULE_INFO_REQUEST 36216
+#define PM_LOAD_MODULE_SECTION_INFO_REQUEST 36218
+#define PM_LOAD_MODULE_SECTION_INFO_REPLY 36219
+
+typedef uint32_t MonitorScopeType;
+
+typedef struct MonitorScope
+{
+ MonitorScopeType type;
+ uint32_t id;
+} MonitorScope;
+
+typedef uint32_t MonitorRegisterId;
+
+typedef struct MonitorGetRegisterInfoRequest
+{
+ uint32_t sigNo;
+ uint32_t reserved0;
+ MonitorScope scope;
+ uint32_t reserved1;
+ uint32_t registersCount;
+ MonitorRegisterId registers[1];
+} MonitorGetRegisterInfoRequest;
+
+typedef uint32_t MonitorStatus;
+
+typedef struct MonitorRegister
+{
+ MonitorRegisterId id;
+ uint32_t value;
+} MonitorRegister;
+
+typedef struct MonitorRegisterValues
+{
+ uint32_t sigNo;
+ uint32_t pid;
+ MonitorStatus status;
+ uint32_t registersCount;
+ MonitorRegister registers[1];
+} MonitorRegisterValues;
+
+typedef uint32_t MonitorProcessType;
+typedef uint32_t MonitorProcessState;
+
+typedef struct MonitorGetProcessInfoReply
+{
+ uint32_t sigNo;
+ uint32_t pid;
+ uint32_t bid;
+ uint32_t sid;
+ MonitorProcessType type;
+ MonitorProcessState state;
+ uint32_t priority;
+ uint32_t entrypoint;
+ uint32_t properties;
+ uint32_t reserved1;
+ char name[1];
+} MonitorGetProcessInfoReply;
+
+#define MONITOR_REGISTER_INVALID 0x80000000
+
+#define MONITOR_REGISTER_IS_INVALID(MONITOR_REGISTER) \
+ (((MONITOR_REGISTER) & MONITOR_REGISTER_INVALID) >> 31)
+
+static const char *
+ose_signal_to_str (int sig)
+{
+ static char buffer[512];
+
+#define SIGNAL(SIG) case SIG: \
+ sprintf (buffer, "%s: 0x%x (%d)", #SIG, SIG, SIG); \
+ break
+
+ switch (sig)
+ {
+ SIGNAL (MONITOR_INTERFACE_REQUEST);
+ SIGNAL (MONITOR_CONNECT_REQUEST);
+ SIGNAL (MONITOR_GET_PROCESS_INFO_REQUEST);
+ SIGNAL (MONITOR_GET_BLOCK_INFO_REQUEST);
+ SIGNAL (MONITOR_GET_SEGMENT_INFO_REQUEST);
+ SIGNAL (MONITOR_GET_REGISTER_INFO_REQUEST);
+
+ SIGNAL (MONITOR_GET_TRACE_REQUEST);
+
+ SIGNAL (PM_PROGRAMS_REQUEST);
+ SIGNAL (PM_PROGRAM_INFO_REQUEST);
+ SIGNAL (PM_LOAD_MODULE_INSTALL_HANDLES_REQUEST);
+ SIGNAL (PM_LOAD_MODULE_INFO_REQUEST);
+ SIGNAL (PM_LOAD_MODULE_SECTION_INFO_REQUEST);
+ default:
+ sprintf (buffer, "unknown OSE signal 0x%x (%d)", sig, sig);
+ break;
+ }
+
+ return buffer;
+}
+
+/* RAM Dump File format grammar:
+
+ Chunk ::= ID Size U32*
+ GroupChunk ::= ID Size SubID (Chunk | GroupChunk)*
+ ID ::= U32
+ Size ::= BigEndianU32
+
+ Dump ::= 'FORM' Size 'PMD ' (Vers | DumpId | BlockList)*
+ Vers ::= 'VERS' Size(4) U32(<version>)
+ DumpId ::= 'DPID' Size(4) U32(<dump id>)
+ BlockList ::= 'LIST' Size 'BLOC' (BlockForm)*
+ BlockForm ::= 'FORM' Size 'BLOC' (BlockChunk)*
+ BlockChunk ::= BlockHead | ErrorForm | TextForm | MemoryForm
+ BlockHead ::= 'BLHD' Size(16) U32(<dump id>) U32(<block no>)
+ U32(<seconds since Jan 1 1970, 00:00>)
+ U32(<additional microseconds>)
+ ErrorForm ::= 'FORM' Size 'ERBL' (Descr | ErrInfo)*
+ Descr ::= 'DESC' Size(<size of text>) <text>
+ ErrInfo ::= 'ERIN' Size(16) U32(<user_called>) U32(<error_code>)
+ U32(<extra>) U32(<curr_proc>)
+ TextForm ::= 'FORM' Size 'TXBL' (Descr)*
+ MemoryForm ::= 'FORM' Size 'MBL ' (Descr | (MemDef (Data | Zdata)))*
+ MemDef ::= 'MHD' Size(8) U32(<start>) U32(<length>)
+ Data ::= 'DATA' Size(<length of data>) <data>
+ Zdata ::= 'FORM' Size 'ZDAT' Zdef Data
+ Zdef ::= 'ZDEF' Size U32(<method>) U32[4](<parameters>)
+ U32(<image_length>) U32(<reserved>)
+*/
+
+/* IDs for the above grammar. */
+
+#define ID_PMD MakeID ('P','M','D',' ')
+#define ID_VERS MakeID ('V','E','R','S')
+#define ID_DPID MakeID ('D','P','I','D')
+#define ID_BLOC MakeID ('B','L','O','C')
+#define ID_BLHD MakeID ('B','L','H','D')
+#define ID_ERBL MakeID ('E','R','B','L')
+#define ID_TXBL MakeID ('T','X','B','L')
+#define ID_MBL MakeID ('M','B','L',' ')
+#define ID_SGBL MakeID ('S','G','B','L')
+#define ID_SGHD MakeID ('S','G','H','D')
+#define ID_DATA MakeID ('D','A','T','A')
+#define ID_ZDAT MakeID ('Z','D','A','T')
+#define ID_DESC MakeID ('D','E','S','C')
+#define ID_ERIN MakeID ('E','R','I','N')
+#define ID_MHD MakeID ('M','H','D',' ')
+#define ID_ZDEF MakeID ('Z','D','E','F')
+
+/* FIXME: should not be a global. */
+int last_data_section;
+
+/* We don't parse any properties, so we don't need to extend the
+ client frame. */
+typedef struct pmd_frame
+{
+ iff_client_frame client_frame;
+} pmd_frame;
+
+static IFFP
+read_U32 (iff_group_context *ctx, U32 *u32p)
+{
+ IFFP iffp = iff_read_bytes (ctx, (bfd_byte *) u32p, sizeof (U32));
+ *u32p = bfd_get_32 (ctx->abfd, u32p);
+ return iffp;
+}
+
+static bfd_byte *
+get_U32 (iff_group_context *ctx, bfd_byte *p, U32 *u32p)
+{
+ memcpy (u32p, p, 4);
+ p += 4;
+ *u32p = bfd_get_32 (ctx->abfd, u32p);
+ return p;
+}
+
+static IFFP
+get_Descr (iff_group_context *ctx, char **desc)
+{
+ IFFP iffp;
+ int size_of_text = ctx->ck_hdr.size;
+ char *buf = bfd_malloc (size_of_text + 1);
+
+ iffp = iff_read_bytes (ctx, (bfd_byte *) buf, size_of_text);
+
+ if (iffp == IFF_OKAY)
+ {
+ buf[size_of_text] = 0;
+ *desc = buf;
+ }
+ else
+ {
+ free (buf);
+ *desc = NULL;
+ }
+
+ return iffp;
+}
+
+static IFFP
+get_ErrorForm (iff_group_context *parent)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+
+ ose_debug ("Got ErrorForm\n");
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = iff_skip_group;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ do
+ {
+ iffp = iff_get_form_chunk_header (&form_context);
+ if (iffp == ID_DESC)
+ {
+ char *desc;
+
+ iffp = get_Descr (&form_context, &desc);
+ if (iffp == IFF_OKAY)
+ {
+ ose_debug ("ErrorForm description = %s\n", desc);
+ free (desc);
+ }
+ }
+ else if (iffp == ID_ERIN)
+ {
+ U32 user_called, error_code, extra, curr_proc;
+
+ iffp = read_U32 (&form_context, &user_called);
+ iffp = read_U32 (&form_context, &error_code);
+ iffp = read_U32 (&form_context, &extra);
+ iffp = read_U32 (&form_context, &curr_proc);
+
+ if (iffp == IFF_OKAY)
+ {
+ ose_debug ("user_called = 0x%x\n", user_called);
+ ose_debug ("error_code = 0x%x\n", error_code);
+ ose_debug ("extra = 0x%x\n", extra);
+ ose_debug ("curr_proc = 0x%x\n", curr_proc);
+ }
+ }
+ } while (iffp >= IFF_OKAY);
+
+ iff_close_read_group (&form_context);
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+static IFFP
+get_TextForm (iff_group_context *parent)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+
+ ose_debug ("Got TextForm\n");
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = iff_skip_group;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ do
+ {
+ iffp = iff_get_form_chunk_header (&form_context);
+ if (iffp == ID_DESC)
+ {
+ char *desc;
+
+ iffp = get_Descr (&form_context, &desc);
+ if (iffp == IFF_OKAY)
+ {
+ ose_debug ("TextForm description = %s\n", desc);
+ free (desc);
+ }
+ }
+ else if (iffp == ID_ERIN)
+ {
+ U32 user_called, error_code, extra, curr_proc;
+
+ iffp = read_U32 (&form_context, &user_called);
+ iffp = read_U32 (&form_context, &error_code);
+ iffp = read_U32 (&form_context, &extra);
+ iffp = read_U32 (&form_context, &curr_proc);
+
+ if (iffp == IFF_OKAY)
+ {
+ ose_debug ("user_called = 0x%x\n", user_called);
+ ose_debug ("error_code = 0x%x\n", error_code);
+ ose_debug ("extra = 0x%x\n", extra);
+ ose_debug ("curr_proc = 0x%x\n", curr_proc);
+ }
+ }
+ } while (iffp >= IFF_OKAY);
+
+ iff_close_read_group (&form_context);
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+static IFFP
+get_MemDef (iff_group_context *ctx, U32 *start, U32 *length)
+{
+ IFFP iffp;
+
+ iffp = read_U32 (ctx, start);
+ iffp = read_U32 (ctx, length);
+
+ return iffp;
+}
+
+static bfd_byte *get_DataOrZdat (iff_group_context *ctx, bfd_byte *buf,
+ size_t length);
+
+static IFFP
+get_MemoryForm (iff_group_context *parent)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+
+ ose_debug ("Got MemoryForm\n");
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = iff_skip_group;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ do
+ {
+ iffp = iff_get_form_chunk_header (&form_context);
+ if (iffp == ID_DESC)
+ {
+ char *desc;
+
+ iffp = get_Descr (&form_context, &desc);
+ if (iffp == IFF_OKAY)
+ {
+ ose_debug ("TextForm description = %s\n", desc);
+ free (desc);
+ }
+ }
+ else if (iffp == ID_MHD)
+ {
+ U32 start, length;
+
+ iffp = get_MemDef (&form_context, &start, &length);
+
+ if (iffp == IFF_OKAY)
+ {
+ bfd_byte *data, *mem;
+
+ ose_debug ("start = 0x%x\n", start);
+ ose_debug ("length = 0x%x\n", length);
+
+ data = bfd_malloc (length);
+
+ mem = get_DataOrZdat (&form_context, data, length);
+
+ if (mem != NULL)
+ {
+ flagword flags;
+ asection *asect;
+ char buf[100];
+ bfd *abfd = form_context.abfd;
+ size_t len;
+ char *sect_name;
+
+ sprintf (buf, "mem%d", last_data_section);
+
+ /* Build the section name. */
+
+ len = strlen (buf) + 1;
+ sect_name = (char *) bfd_alloc (abfd, len);
+ if (sect_name == NULL)
+ ;
+ else
+ {
+ memcpy (sect_name, buf, len);
+
+ flags = (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS | SEC_IN_MEMORY);
+ asect = bfd_make_section_anyway_with_flags (abfd,
+ sect_name,
+ flags);
+ if (asect == NULL)
+ {
+ /* warn? */
+ }
+ else
+ {
+ asect->size = length;
+ asect->vma = start;
+ asect->filepos = 0;
+ asect->contents = mem;
+
+ last_data_section++;
+ }
+ }
+ }
+
+ free (data);
+ }
+ }
+ } while (iffp >= IFF_OKAY);
+
+ iff_close_read_group (&form_context);
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+/* Decompress a chunk that was compressed using zlib. */
+
+#ifdef HAVE_ZLIB_H
+
+static bfd_boolean
+zlib_inflate_buffer (bfd_byte *compressed_buffer,
+ size_t compressed_size,
+ bfd_byte *uncompressed_buffer,
+ bfd_size_type uncompressed_size)
+{
+ z_stream strm;
+ int rc;
+
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+ strm.avail_in = compressed_size;
+ strm.next_in = (Bytef *) compressed_buffer;
+ strm.avail_out = uncompressed_size;
+
+ rc = inflateInit (&strm);
+ while (strm.avail_in > 0)
+ {
+ if (rc != Z_OK)
+ return FALSE;
+ strm.next_out = ((Bytef *) uncompressed_buffer
+ + (uncompressed_size - strm.avail_out));
+ rc = inflate (&strm, Z_FINISH);
+ if (rc != Z_STREAM_END)
+ return FALSE;
+ rc = inflateReset (&strm);
+ }
+ rc = inflateEnd (&strm);
+ if (rc != Z_OK
+ || strm.avail_out != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+#endif
+
+#define RAMDUMP_COMPRESS_ZLIB_Z77 ((U32) 0x1)
+
+static IFFP
+get_Zdata (iff_group_context *parent, bfd_byte *buf, size_t length)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+
+ /* Just ignore unknown forms. */
+ if (parent->subtype != ID_ZDAT)
+ return IFF_OKAY;
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = iff_skip_group;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ iffp = iff_get_form_chunk_header (&form_context);
+
+ if (iffp == ID_ZDEF)
+ {
+ U32 method;
+ U32 parameters[4];
+ U32 image_length;
+ U32 reserved;
+
+ bfd_byte *compressed;
+ int i;
+
+ iffp = read_U32 (&form_context, &method);
+ for (i = 0; i < 4; i++)
+ iffp = read_U32 (&form_context, ¶meters[i]);
+ iffp = read_U32 (&form_context, &image_length);
+ iffp = read_U32 (&form_context, &reserved);
+
+ if (method == RAMDUMP_COMPRESS_ZLIB_Z77)
+ {
+ iffp = iff_get_form_chunk_header (&form_context);
+
+ if (iffp == ID_DATA)
+ {
+ /* FIXME: we could get away with this bfd_malloc. */
+ compressed = bfd_malloc (image_length);
+ iffp = iff_read_bytes (&form_context, compressed, image_length);
+
+#ifdef HAVE_ZLIB_H
+ if (!zlib_inflate_buffer (compressed, image_length,
+ buf, length))
+ iffp = BAD_IFF;
+ else
+#endif
+ iffp = END_MARK;
+ }
+ else
+ (*_bfd_error_handler)
+ (_("warning: missing DATA chunk"));
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ (_("warning: unsupported compression method: %d"), method);
+ }
+ }
+ else
+ {
+ (*_bfd_error_handler)
+ (_("warning: missing zdef"));
+ }
+
+ iff_close_read_group (&form_context);
+ return (iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+static bfd_byte *
+get_DataOrZdat (iff_group_context *ctx, bfd_byte *buf, size_t length)
+{
+ IFFP iffp;
+
+ iffp = iff_get_form_chunk_header (ctx);
+
+ if (iffp == ID_DATA)
+ {
+ iffp = iff_read_bytes (ctx, buf, length);
+ return buf;
+ }
+ else if (iffp == FORM && ctx->subtype == ID_ZDAT)
+ {
+ iffp = get_Zdata (ctx, buf, length);
+ return buf;
+ }
+ else
+ return NULL;
+}
+
+static void
+swap_in_MonitorGetRegisterInfoRequest (bfd *abfd,
+ MonitorGetRegisterInfoRequest *sig)
+{
+ uint32_t i;
+
+ sig->sigNo = bfd_get_32 (abfd, &sig->sigNo);
+ sig->reserved0 = bfd_get_32 (abfd, &sig->reserved0);
+ sig->scope.type = bfd_get_32 (abfd, &sig->scope.type);
+ sig->scope.id = bfd_get_32 (abfd, &sig->scope.id);
+ sig->reserved1 = bfd_get_32 (abfd, &sig->reserved1);
+ sig->registersCount = bfd_get_32 (abfd, &sig->registersCount);
+
+ for (i = 0; i < sig->registersCount; i++)
+ sig->registers[i] = bfd_get_32 (abfd, &sig->registers[i]);
+}
+
+static void
+swap_in_MonitorRegisterValues (bfd *abfd, MonitorRegisterValues *sig)
+{
+ uint32_t i;
+
+ sig->sigNo = bfd_get_32 (abfd, &sig->sigNo);
+ sig->pid = bfd_get_32 (abfd, &sig->pid);
+ sig->status = bfd_get_32 (abfd, &sig->status);
+ sig->registersCount = bfd_get_32 (abfd, &sig->registersCount);
+
+ for (i = 0; i < sig->registersCount; i++)
+ {
+ sig->registers[i].id = bfd_get_32 (abfd, &sig->registers[i].id);
+ // sig->registers[i].value = bfd_get_32 (abfd, &sig->registers[i].value);
+ }
+}
+
+static void
+swap_in_MonitorGetProcessInfoReply (bfd *abfd, MonitorGetProcessInfoReply *sig)
+{
+ sig->sigNo = bfd_get_32 (abfd, &sig->sigNo);
+ sig->pid = bfd_get_32 (abfd, &sig->pid);
+ sig->bid = bfd_get_32 (abfd, &sig->bid);
+ sig->sid = bfd_get_32 (abfd, &sig->sid);
+ sig->type = bfd_get_32 (abfd, &sig->type);
+ sig->state = bfd_get_32 (abfd, &sig->state);
+ sig->priority = bfd_get_32 (abfd, &sig->priority);
+ sig->entrypoint = bfd_get_32 (abfd, &sig->entrypoint);
+ sig->properties = bfd_get_32 (abfd, &sig->properties);
+ sig->reserved1 = bfd_get_32 (abfd, &sig->reserved1);
+}
+
+#define ose_core_tdata(bfd) \
+ ((bfd) -> tdata.ose_core_data)
+
+/* If there isn't a section called NAME, make one, using data from
+ SECT. Note, this function will generate a reference to NAME, so
+ you shouldn't deallocate or overwrite it. */
+
+static bfd_boolean
+maybe_make_sect (bfd *abfd, char *name, asection *sect)
+{
+ asection *sect2;
+
+ if (bfd_get_section_by_name (abfd, name) != NULL)
+ return TRUE;
+
+ sect2 = bfd_make_section_with_flags (abfd, name, sect->flags);
+ if (sect2 == NULL)
+ return FALSE;
+
+ sect2->size = sect->size;
+ sect2->filepos = sect->filepos;
+ sect2->alignment_power = sect->alignment_power;
+ sect2->contents = bfd_malloc (sect->size);
+ memcpy (sect2->contents, sect->contents, sect->size);
+ return TRUE;
+}
+
+/* Create a pseudosection containing a copy of the buffer CONTENTS of
+ SIZE bytes. This actually creates up to two pseudosections:
+
+ - A section named "NAME/PID".
+ - A section named NAME, unless such a section already exists. GDB
+ uses this section to select the current thread.
+
+ Both pseudosections have identical contents. */
+
+static bfd_boolean
+make_pseudosection (bfd *abfd, char *name, U32 pid,
+ bfd_byte *contents, size_t size)
+{
+ char buf[100];
+ char *threaded_name;
+ size_t len;
+ asection *sect;
+
+ /* Build the section name. */
+
+ sprintf (buf, "%s/%d", name, pid);
+ len = strlen (buf) + 1;
+ threaded_name = (char *) bfd_alloc (abfd, len);
+ if (threaded_name == NULL)
+ return FALSE;
+ memcpy (threaded_name, buf, len);
+
+ sect = bfd_make_section_anyway_with_flags (abfd, threaded_name,
+ SEC_HAS_CONTENTS | SEC_IN_MEMORY);
+ if (sect == NULL)
+ return FALSE;
+ sect->size = size;
+ sect->filepos = 0;
+ sect->alignment_power = 2;
+ sect->contents = bfd_malloc (size);
+ memcpy (sect->contents, contents, size);
+
+ return maybe_make_sect (abfd, name, sect);
+}
+
+static asection *
+make_section_for_signal (bfd *abfd, const char *sect_name,
+ bfd_byte *sig, size_t length)
+{
+ flagword flags;
+ asection *asect;
+ size_t len;
+ char *copy;
+
+ /* Build the section name. */
+
+ len = strlen (sect_name) + 1;
+ copy = (char *) bfd_alloc (abfd, len);
+ if (copy == NULL)
+ return NULL;
+
+ memcpy (copy, sect_name, len);
+
+ flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY;
+ asect = bfd_make_section_anyway_with_flags (abfd, copy, flags);
+ if (asect == NULL)
+ return NULL;
+
+ asect->size = length;
+ asect->vma = 0;
+ asect->filepos = 0;
+ asect->contents = bfd_malloc (length);
+ memcpy (asect->contents, sig, length);
+
+ return asect;
+}
+
+static IFFP
+get_SigDef (iff_group_context *ctx)
+{
+ IFFP iffp;
+ U32 signo, status, length;
+
+ /* Each signal chunk contains a compressed sequence of C structs
+ where each C struct corresponds to a signal in a
+ request/reply(/endmark) signal transaction.
+
+ For example, the CPU registers are stored in a signal chunk as a
+ signal transaction consisting of the following signals:
+
+ MONITOR_GET_REGISTERS_INFO_REQUEST (MonitorGetRegisterInfoRequest struct)
+ MONITOR_GET_REGISTERS_REPLY (MonitorRegisterValues struct)
+
+ The actual structs are laid out consecutively in the following
+ manner in the SignalForm->Zdata->Data chunk:
+
+ (U32(<sigsize>) U32(<signo>) U32(<data>) <padding>)*
+ */
+
+ iffp = iff_get_form_chunk_header (ctx);
+ if (iffp != ID_SGHD)
+ return iffp;
+
+ iffp = read_U32 (ctx, &signo);
+ iffp = read_U32 (ctx, &status);
+ iffp = read_U32 (ctx, &length);
+
+ if (iffp == IFF_OKAY)
+ {
+ bfd_byte *data;
+ bfd_byte *sig;
+
+ ose_debug ("signal = %s\n", ose_signal_to_str (signo));
+ ose_debug ("status = 0x%x (%d)\n", status, status);
+ ose_debug ("length = 0x%x (%d)\n", length, length);
+
+ data = bfd_malloc (length);
+
+ sig = get_DataOrZdat (ctx, data, length);
+ if (sig == NULL)
+ ;
+ else
+ {
+ bfd_byte *end = sig + length;
+
+ while (sig < end)
+ {
+ U32 data_sigsize, data_signo;
+
+ sig = get_U32 (ctx, sig, &data_sigsize);
+ get_U32 (ctx, sig, &data_signo);
+
+ ose_debug ("data signal = %s\n", ose_signal_to_str (data_signo));
+
+ if (data_signo == MONITOR_GET_REGISTER_INFO_REQUEST)
+ {
+ MonitorGetRegisterInfoRequest *req = (void *) sig;
+
+ swap_in_MonitorGetRegisterInfoRequest (ctx->abfd, req);
+
+ ose_debug ("length = 0x%x (%d)\n", length, length);
+ }
+ else if (data_signo == MONITOR_GET_REGISTERS_REPLY)
+ {
+ MonitorRegisterValues *reply = (void *) sig;
+ bfd *abfd = ctx->abfd;
+
+ swap_in_MonitorRegisterValues (ctx->abfd, reply);
+
+ /* Sometimes OSE dumps two chunks containing
+ registers. The registers that are marked as
+ valid in the second chunk should replace the
+ corresponding registers in the first chunk.
+ Don't ask... */
+
+ /* FIXME: we should be merging the registers sets,
+ not just blindly taking the latter one. */
+ if (reply->registersCount > 0
+ && !MONITOR_REGISTER_IS_INVALID (reply->registers[0].id))
+ {
+ /* Make a ".reg/999" section and a ".reg" section. */
+ make_pseudosection (abfd, ".reg", reply->pid,
+ sig, data_sigsize);
+ ose_debug ("found registers for pid=0x%x\n", reply->pid);
+ }
+ else
+ ose_debug ("found invalid registers for pid=0x%x."
+ " ignoring\n", reply->pid);
+ }
+ else if (data_signo == MONITOR_GET_PROCESS_INFO_REPLY)
+ {
+ MonitorGetProcessInfoReply *reply = (void *) sig;
+
+ swap_in_MonitorGetProcessInfoReply (ctx->abfd, reply);
+
+ ose_debug ("found process = pid=0x%x,"
+ "bid=0x%x,sid=0x%x,name=%s\n",
+ reply->pid, reply->bid, reply->sid, reply->name);
+ }
+ else if (data_signo == PM_LOAD_MODULE_SECTION_INFO_REPLY)
+ {
+ asection *asect;
+ bfd *abfd = ctx->abfd;
+
+ asect = make_section_for_signal (abfd, ".section-info",
+ sig, data_sigsize);
+ if (asect == NULL)
+ {
+ /* warn? */
+ }
+ }
+
+ sig += data_sigsize;
+ sig += (4 - (data_sigsize % 4)) % 4;
+ }
+ }
+
+ free (data);
+ }
+
+ return iffp;
+}
+
+static IFFP
+get_SignalForm (iff_group_context *parent)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+
+ /* Just ignore unknown forms. */
+ if (parent->subtype != ID_SGBL)
+ return IFF_OKAY;
+
+ ose_debug ("Got SignalForm\n");
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = iff_skip_group;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ do
+ {
+ iffp = get_SigDef (&form_context);
+ } while (iffp >= IFF_OKAY);
+
+ iff_close_read_group (&form_context);
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+static IFFP
+get_BlockForm (iff_group_context *parent)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+
+ /* Just ignore unknown forms. */
+ if (parent->subtype != ID_BLOC)
+ return IFF_OKAY;
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = get_SignalForm;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ do
+ {
+ iffp = iff_get_form_chunk_header (&form_context);
+ if (iffp == ID_BLHD)
+ {
+ U32 dump_id, block_no, sepoc, us;
+
+ iffp = read_U32 (&form_context, &dump_id);
+ iffp = read_U32 (&form_context, &block_no);
+ iffp = read_U32 (&form_context, &sepoc);
+ iffp = read_U32 (&form_context, &us);
+
+ if (iffp == IFF_OKAY)
+ {
+ ose_debug ("BLHD\n");
+ ose_debug ("..dump id = %u\n", dump_id);
+ ose_debug ("..block no = %u\n", block_no);
+ ose_debug ("..seconds since epoc = %u\n", sepoc);
+ ose_debug ("..additional microseconds = %u\n", us);
+ }
+ }
+ else if (iffp == FORM && form_context.subtype == ID_ERBL)
+ {
+ ose_debug ("Got ID_ERBL\n");
+ iffp = get_ErrorForm (&form_context);
+ }
+ else if (iffp == FORM && form_context.subtype == ID_TXBL)
+ {
+ ose_debug ("Got ID_TXBL\n");
+ iffp = get_TextForm (&form_context);
+ }
+ else if (iffp == FORM && form_context.subtype == ID_MBL)
+ {
+ ose_debug ("Got ID_MBL\n");
+ iffp = get_MemoryForm (&form_context);
+ }
+ else if (iffp == FORM && form_context.subtype == ID_SGBL)
+ {
+ iffp = get_SignalForm (&form_context);
+ }
+ } while (iffp >= IFF_OKAY);
+
+ iff_close_read_group (&form_context);
+ return(iffp == END_MARK ? IFF_OKAY : iffp);
+}
+
+static IFFP
+read_BlockList (iff_group_context *parent)
+{
+ pmd_frame new_frame;
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = get_BlockForm;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ return iff_read_list (parent, (iff_client_frame *) &new_frame);
+}
+
+static IFFP
+get_Dump (iff_group_context *parent)
+{
+ IFFP iffp;
+ iff_group_context form_context;
+ pmd_frame new_frame;
+ U32 version = 0;
+ U32 dump_id = 0;
+
+ /* Just ignore unknown forms. */
+ if (parent->subtype != ID_PMD)
+ return IFF_OKAY;
+
+ new_frame = *(pmd_frame *) parent->client_frame;
+
+ new_frame.client_frame.get_list = iff_skip_group;
+ new_frame.client_frame.get_prop = iff_skip_group;
+ new_frame.client_frame.get_form = iff_skip_group;
+ new_frame.client_frame.get_cat = iff_skip_group;
+
+ iffp = iff_open_read_group (parent, &form_context);
+ if (iffp != IFF_OKAY)
+ return iffp;
+ form_context.client_frame = &new_frame.client_frame;
+
+ do
+ {
+ iffp = iff_get_form_chunk_header (&form_context);
+
+ if (iffp == LIST && form_context.subtype == ID_BLOC)
+ {
+ iffp = read_BlockList (&form_context);
+ }
+ else if (iffp == ID_VERS)
+ {
+ iffp = read_U32 (&form_context, &version);
+ ose_debug ("version = %d\n", version);
+ }
+ else if (iffp == ID_DPID)
+ {
+ iffp = read_U32 (&form_context, &dump_id);
+ ose_debug ("dump id = %d\n", dump_id);
+ }
+ else if (iffp == END_MARK)
+ iffp = IFF_DONE;
+ } while (iffp >= IFF_OKAY);
+
+ if (iffp != IFF_DONE)
+ return iffp;
+
+ /* If we get this far, there were no errors. */
+ iff_close_read_group (&form_context);
+ return iffp;
+}
+
+static IFFP
+read_pmd (bfd *file, pmd_frame *iFrame)
+{
+ iFrame->client_frame.get_list = iff_skip_group;
+ iFrame->client_frame.get_prop = iff_skip_group;
+ iFrame->client_frame.get_form = get_Dump;
+ iFrame->client_frame.get_cat = iff_skip_group;
+
+ return iff_read (file, (iff_client_frame *) iFrame);
+}
+
+
+
+#define ose_core_file_matches_executable_p \
+ generic_core_file_matches_executable_p
+
+static int
+ose_core_file_pid (bfd *abfd)
+{
+ return ose_core_tdata (abfd)->bid;
+}
+
+static const bfd_target *
+ose_core_file_p (bfd *abfd)
+{
+ bfd_size_type amt;
+ IFFP iffp;
+ pmd_frame iFrame;
+
+#ifndef HAVE_ZLIB_H
+ return NULL;
+#endif
+
+ iffp = read_pmd (abfd, &iFrame);
+ if (iffp == BAD_IFF || iffp == NOT_IFF)
+ return NULL;
+
+ if (iffp != IFF_DONE)
+ ose_debug ("iffp = 0x%x (%d)\n", iffp, iffp);
+
+ /* OK, we believe you. You're a core file. */
+
+ /* FIXME: this is too late here. We'll want to record here things
+ like the core's pid, while inside read_pmd above. Make this
+ allocation lazy within ose_core_tdata? */
+ amt = sizeof (struct ose_core_struct);
+ abfd->tdata.ose_core_data = (struct ose_core_struct *) bfd_zmalloc (amt);
+ if (abfd->tdata.ose_core_data == NULL)
+ return NULL;
+
+ /* FIXME: should be set from what the PMD says it is. */
+ bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc);
+
+ return abfd->xvec;
+
+ /* Get here if we have already started filling out the BFD
+ and there is an error of some kind. */
+
+ /* FIXME: not reacheable. */
+ goto error_return;
+ error_return:
+ bfd_release (abfd, abfd->tdata.any);
+ abfd->tdata.any = NULL;
+ bfd_section_list_clear (abfd);
+ return NULL;
+}
+
+static char *
+ose_core_file_failing_command (bfd *abfd ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
+
+static int
+ose_core_file_failing_signal (bfd *abfd ATTRIBUTE_UNUSED)
+{
+ return abfd->tdata.ose_core_data->sig;
+}
+
+extern const bfd_target ose_core_little_vec;
+
+const bfd_target ose_core_big_vec =
+ {
+ "ose-core-big",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_BIG, /* target byte order */
+ BFD_ENDIAN_BIG, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* symbol prefix */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 0, /* match priority. */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* data */
+ bfd_getb64, bfd_getb_signed_64, bfd_putb64,
+ bfd_getb32, bfd_getb_signed_32, bfd_putb32,
+ bfd_getb16, bfd_getb_signed_16, bfd_putb16, /* hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ ose_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (ose),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
+ BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+ BFD_JUMP_TABLE_WRITE (_bfd_generic),
+ BFD_JUMP_TABLE_LINK (_bfd_nolink),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ &ose_core_little_vec,
+
+ NULL /* backend_data */
+ };
+
+const bfd_target ose_core_little_vec =
+ {
+ "ose-core-little",
+ bfd_target_unknown_flavour,
+ BFD_ENDIAN_LITTLE, /* target byte order */
+ BFD_ENDIAN_LITTLE, /* target headers byte order */
+ (HAS_RELOC | EXEC_P | /* object flags */
+ HAS_LINENO | HAS_DEBUG |
+ HAS_SYMS | HAS_LOCALS | WP_TEXT | D_PAGED),
+ (SEC_HAS_CONTENTS | SEC_ALLOC | SEC_LOAD | SEC_RELOC), /* section flags */
+ 0, /* symbol prefix */
+ ' ', /* ar_pad_char */
+ 16, /* ar_max_namelen */
+ 0, /* match priority. */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* data */
+ bfd_getl64, bfd_getl_signed_64, bfd_putl64,
+ bfd_getl32, bfd_getl_signed_32, bfd_putl32,
+ bfd_getl16, bfd_getl_signed_16, bfd_putl16, /* hdrs */
+
+ { /* bfd_check_format */
+ _bfd_dummy_target, /* unknown format */
+ _bfd_dummy_target, /* object file */
+ _bfd_dummy_target, /* archive */
+ ose_core_file_p /* a core file */
+ },
+ { /* bfd_set_format */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+ { /* bfd_write_contents */
+ bfd_false, bfd_false,
+ bfd_false, bfd_false
+ },
+
+ BFD_JUMP_TABLE_GENERIC (_bfd_generic),
+ BFD_JUMP_TABLE_COPY (_bfd_generic),
+ BFD_JUMP_TABLE_CORE (ose),
+ BFD_JUMP_TABLE_ARCHIVE (_bfd_noarchive),
+ BFD_JUMP_TABLE_SYMBOLS (_bfd_nosymbols),
+ BFD_JUMP_TABLE_RELOCS (_bfd_norelocs),
+ BFD_JUMP_TABLE_WRITE (_bfd_generic),
+ BFD_JUMP_TABLE_LINK (_bfd_nolink),
+ BFD_JUMP_TABLE_DYNAMIC (_bfd_nodynamic),
+
+ &ose_core_big_vec,
+
+ NULL /* backend_data */
+ };
--- a/bfd/targets.c
+++ b/bfd/targets.c
@@ -894,6 +894,8 @@ extern const bfd_target x86_64pei_vec;
extern const bfd_target x86_64coff_vec;
extern const bfd_target z80coff_vec;
extern const bfd_target z8kcoff_vec;
+extern const bfd_target ose_core_big_vec;
+extern const bfd_target ose_core_little_vec;
/* These are always included. */
extern const bfd_target srec_vec;
More information about the Binutils
mailing list