#ifndef __GDB_MACOSX_NAT_DYLD_INFO_H__
#define __GDB_MACOSX_NAT_DYLD_INFO_H__

#include "defs.h"

struct _bfd;

typedef enum dyld_objfile_reason
{

  dyld_reason_deallocated = 0x0000,

  dyld_reason_user = 0x0001,
  dyld_reason_init = 0x0002,
  dyld_reason_executable = 0x0004,
  dyld_reason_dyld = 0x0008,
  dyld_reason_cfm = 0x0010,

  dyld_reason_executable_mask = 0x0004,

  dyld_reason_type_mask = 0x00ff,
  dyld_reason_flags_mask = 0xff00,

  dyld_reason_image_mask = 0x0006,

  dyld_reason_cached_mask = 0x0100,
  dyld_reason_weak_mask = 0x0200,
  dyld_reason_cached_weak_mask = 0x0300,

  dyld_reason_all_mask = 0xfffe
} dyld_objfile_reason;


/* There is one struct dyld_objfile_entry for each file image that
   the program has loaded, or will load.  */

struct dyld_objfile_entry
{
  const char *prefix;  /* "__dyld_" for the dyld image file by default */

  CORE_ADDR dyld_addr;
  CORE_ADDR dyld_slide;
  CORE_ADDR dyld_length;

  /* This boolean seems to indicate that dyld has told us about this particular
      dyld_objfile_entry.  I guess that's distinguished from load
      command-discovered images that aren't actually loaded yet?  */

  int dyld_valid;

  unsigned long cfm_container;  /* it really is 32 bits - CFM won't go 64bit */

  /* Names names names.
     Why oh why lord are there all these names? What use can they possibly have? */

  char *user_name;

  char *dyld_name;
  int dyld_name_valid;

  char *image_name;
  int image_name_valid;

  CORE_ADDR image_addr;
  int image_addr_valid;

  char *text_name;
  int text_name_valid;

  const char *loaded_name;


  struct bfd *abfd;
  struct objfile *objfile;

  struct bfd *commpage_bfd;             /* The BFD for the commpage symbol info */
  struct objfile *commpage_objfile;     /* The corresponding objfile */

  CORE_ADDR loaded_memaddr;
  CORE_ADDR loaded_addr;
  CORE_ADDR loaded_offset;
  int loaded_addrisoffset;
  int loaded_from_memory;
  int loaded_error;

  int load_flag;

  enum dyld_objfile_reason reason;

  /* The array of dyld_objfile_entry's for the inferior process is a little
     sparse -- some of the entries will be used, others will be allocated but
     unused.  This boolean tells us whether this dyld_objfile_entry is used
     or not.  */

  int allocated;
};


/* There is one struct dyld_objfile_info per inferior process.  */

struct dyld_objfile_info
{
  struct dyld_objfile_entry *entries;
  int nents;
  int maxents;
  struct obj_section *sections;
  struct obj_section *sections_end;
};

struct dyld_path_info;

enum
{
  DYLD_ENTRY_FILENAME_BASE = 0,
  DYLD_ENTRY_FILENAME_LOADED = 1,
  DYLD_ENTRY_FILENAME_USER = 2
} dyld_entry_filename_type;

const char *dyld_entry_filename (const struct dyld_objfile_entry *e,
                                 const struct dyld_path_info *d, int type);

char *dyld_offset_string (CORE_ADDR offset);

char *dyld_entry_string (struct dyld_objfile_entry *e, int use_shortnames);

const char *dyld_reason_string (dyld_objfile_reason r);

void dyld_objfile_entry_clear (struct dyld_objfile_entry *e);

void dyld_objfile_info_init (struct dyld_objfile_info *i);

void dyld_objfile_info_clear_objfiles (struct dyld_objfile_info *i);

void dyld_objfile_info_pack (struct dyld_objfile_info *i);

void dyld_objfile_info_free (struct dyld_objfile_info *i);

void dyld_objfile_info_copy (struct dyld_objfile_info *d,
                             struct dyld_objfile_info *s);

void dyld_objfile_info_copy_entries (struct dyld_objfile_info *d,
                                     struct dyld_objfile_info *s,
                                     unsigned int mask);

struct dyld_objfile_entry *dyld_objfile_entry_alloc (struct dyld_objfile_info *i);

void dyld_print_shlib_info (struct dyld_objfile_info *s,
                            unsigned int reason_mask, int header, char *args);

int dyld_resolve_shlib_num (struct dyld_objfile_info *s, int num,
                            struct dyld_objfile_entry **eptr,
                            struct objfile ** optr);

int dyld_objfile_info_compare (struct dyld_objfile_info *a,
                               struct dyld_objfile_info *b);

void dyld_convert_entry (struct objfile *o, struct dyld_objfile_entry *e);

void dyld_entry_info (struct dyld_objfile_entry *e, int print_basenames,
                      char **in_name, char **in_objname, char **in_symname,
                      char **in_auxobjname, char **in_auxsymname, char **addr,
                      char **slide, char **prefix);

void dyld_print_entry_info (struct dyld_objfile_entry *j, int shlibnum, int baselen);

unsigned int dyld_shlib_info_basename_length (struct dyld_objfile_info *,
                                              unsigned int);

int dyld_entry_shlib_num (struct dyld_objfile_info *s,
                          struct dyld_objfile_entry *eptr,
                          int *numptr);

int dyld_entry_shlib_num_matches (int shlibnum, char *args, int verbose);

unsigned int dyld_next_allocated_shlib (struct dyld_objfile_info *info,
                                        unsigned int n);


/* The one-per-inferior INFO structure has an array of dyld_objfile_entry
   structures, one-per-executable/dylib/bundle/etc.  This macro iterates
   over all the dyld_objfile_entry's in the given INFO, setting O to
   each in turn, and using N to keep track of where it is in the array.
   INFO is type struct dyld_objfile_info
   O is type struct dyld_objfile_entry
   N is type int

   The middle expression in the for loop is equivalent to
     if (n < info->nents)
        o = info->entries[n]
     else
        break;
*/
#define DYLD_ALL_OBJFILE_INFO_ENTRIES(info, o, n)                  \
  for ((n) = dyld_next_allocated_shlib ((info), 0);                \
       ((n) < (info)->nents) ? (o = &(info)->entries[(n)], 1) : 0; \
       (n) = dyld_next_allocated_shlib (info, (n) + 1))

#endif /* __GDB_MACOSX_NAT_DYLD_INFO_H__ */
