tools/elf4rom/libs/dwarf-20071209/libdwarf/dwarf_global.c
changeset 34 92d87f2e53c2
equal deleted inserted replaced
33:1af5c1be89f8 34:92d87f2e53c2
       
     1 /*
       
     2 
       
     3   Copyright (C) 2000,2002,2004,2005 Silicon Graphics, Inc.  All Rights Reserved.
       
     4   Portions Copyright (C) 2007 David Anderson. All Rights Reserved.
       
     5 
       
     6   This program is free software; you can redistribute it and/or modify it
       
     7   under the terms of version 2.1 of the GNU Lesser General Public License 
       
     8   as published by the Free Software Foundation.
       
     9 
       
    10   This program is distributed in the hope that it would be useful, but
       
    11   WITHOUT ANY WARRANTY; without even the implied warranty of
       
    12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
       
    13 
       
    14   Further, this software is distributed without any warranty that it is
       
    15   free of the rightful claim of any third person regarding infringement 
       
    16   or the like.  Any license provided herein, whether implied or 
       
    17   otherwise, applies only to this software file.  Patent licenses, if
       
    18   any, provided herein do not apply to combinations of this program with 
       
    19   other software, or any other product whatsoever.  
       
    20 
       
    21   You should have received a copy of the GNU Lesser General Public 
       
    22   License along with this program; if not, write the Free Software 
       
    23   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
       
    24   USA.
       
    25 
       
    26   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
       
    27   Mountain View, CA 94043, or:
       
    28 
       
    29   http://www.sgi.com
       
    30 
       
    31   For further information regarding this notice, see:
       
    32 
       
    33   http://oss.sgi.com/projects/GenInfo/NoticeExplan
       
    34 
       
    35 */
       
    36 /* The address of the Free Software Foundation is
       
    37    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, 
       
    38    Boston, MA 02110-1301, USA.
       
    39    SGI has moved from the Crittenden Lane address.
       
    40 */
       
    41 
       
    42 
       
    43 
       
    44 
       
    45 #include "config.h"
       
    46 #include "dwarf_incl.h"
       
    47 #include <stdio.h>
       
    48 #include "dwarf_global.h"
       
    49 
       
    50 
       
    51 #ifdef __sgi			/* __sgi should only be defined for
       
    52 				   IRIX/MIPS. */
       
    53 /* The 'fixup' here intended for IRIX targets only.
       
    54    With a  2+GB Elf64 IRIX executable (under 4GB in size),  
       
    55    some DIE offsets wrongly
       
    56    got the 32bit upper bit sign extended.  For the cu-header
       
    57    offset in the .debug_pubnames section  and in the
       
    58    .debug_aranges section.
       
    59    the 'varp' here is a pointer to an offset into .debug_info.
       
    60    We fix up the offset here if it seems advisable..
       
    61    
       
    62    As of June 2005 we have identified a series of mistakes
       
    63    in ldx64 that can cause this (64 bit values getting passed
       
    64    thru 32-bit signed knothole).  
       
    65 */
       
    66 void
       
    67 _dwarf_fix_up_offset_irix(Dwarf_Debug dbg,
       
    68 			  Dwarf_Unsigned * varp, char *caller_site_name)
       
    69 {
       
    70 
       
    71     Dwarf_Unsigned var = *varp;
       
    72 
       
    73 #define UPPER33 0xffffffff80000000LL
       
    74 #define LOWER32         0xffffffffLL
       
    75     /* Restrict the hack to the known case. Upper 32 bits erroneously
       
    76        sign extended from lower 32 upper bit. */
       
    77     if ((var & UPPER33) == UPPER33) {
       
    78 	var &= LOWER32;
       
    79 	/* Apply the fix. Dreadful hack. */
       
    80 	*varp = var;
       
    81     }
       
    82 #undef UPPER33
       
    83 #undef LOWER32
       
    84     return;
       
    85 }
       
    86 #endif
       
    87 
       
    88 
       
    89 int
       
    90 dwarf_get_globals(Dwarf_Debug dbg,
       
    91 		  Dwarf_Global ** globals,
       
    92 		  Dwarf_Signed * return_count, Dwarf_Error * error)
       
    93 {
       
    94     int res;
       
    95 
       
    96     res =
       
    97 	_dwarf_load_section(dbg,
       
    98 			    dbg->de_debug_pubnames_index,
       
    99 			    &dbg->de_debug_pubnames, error);
       
   100     if (res != DW_DLV_OK) {
       
   101 	return res;
       
   102     }
       
   103 
       
   104 
       
   105 
       
   106     return _dwarf_internal_get_pubnames_like_data(dbg,
       
   107 						  dbg->
       
   108 						  de_debug_pubnames,
       
   109 						  dbg->
       
   110 						  de_debug_pubnames_size,
       
   111 						  globals, return_count,
       
   112 						  error,
       
   113 						  DW_DLA_GLOBAL_CONTEXT,
       
   114 						  DW_DLA_GLOBAL,
       
   115 						  DW_DLE_PUBNAMES_LENGTH_BAD,
       
   116 						  DW_DLE_PUBNAMES_VERSION_ERROR);
       
   117 
       
   118 }
       
   119 
       
   120 /* Deallocating fully requires deallocating the list
       
   121    and all entries.  But some internal data is
       
   122    not exposed, so we need a function with internal knowledge.
       
   123 */
       
   124 
       
   125 void
       
   126 dwarf_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
       
   127 		      Dwarf_Signed count)
       
   128 {
       
   129     _dwarf_internal_globals_dealloc(dbg, dwgl,
       
   130 				    count,
       
   131 				    DW_DLA_GLOBAL_CONTEXT,
       
   132 				    DW_DLA_GLOBAL, DW_DLA_LIST);
       
   133     return;
       
   134 }
       
   135 
       
   136 void
       
   137 _dwarf_internal_globals_dealloc(Dwarf_Debug dbg, Dwarf_Global * dwgl,
       
   138 				Dwarf_Signed count,
       
   139 				int context_code,
       
   140 				int global_code, int list_code)
       
   141 {
       
   142     Dwarf_Signed i;
       
   143     struct Dwarf_Global_Context_s *gcp = 0;
       
   144     struct Dwarf_Global_Context_s *lastgcp = 0;
       
   145 
       
   146     for (i = 0; i < count; i++) {
       
   147 	Dwarf_Global dgb = dwgl[i];
       
   148 
       
   149 	gcp = dgb->gl_context;
       
   150 
       
   151 	if (lastgcp != gcp) {
       
   152 	    lastgcp = gcp;
       
   153 	    dwarf_dealloc(dbg, gcp, context_code);
       
   154 	}
       
   155 	dwarf_dealloc(dbg, dgb, global_code);
       
   156     }
       
   157     dwarf_dealloc(dbg, dwgl, list_code);
       
   158     return;
       
   159 }
       
   160 
       
   161 
       
   162 /* Sweeps the complete  section. 
       
   163 */
       
   164 int
       
   165 _dwarf_internal_get_pubnames_like_data(Dwarf_Debug dbg,
       
   166 				       Dwarf_Small * section_data_ptr,
       
   167 				       Dwarf_Unsigned section_length,
       
   168 				       Dwarf_Global ** globals,
       
   169 				       Dwarf_Signed * return_count,
       
   170 				       Dwarf_Error * error,
       
   171 				       int context_code,
       
   172 				       int global_code,
       
   173 				       int length_err_num,
       
   174 				       int version_err_num)
       
   175 {
       
   176 
       
   177 
       
   178     Dwarf_Small *pubnames_like_ptr = 0;
       
   179 
       
   180 
       
   181 
       
   182     /* 
       
   183        Points to the context for the current set of global names, and
       
   184        contains information to identify the compilation-unit that the
       
   185        set refers to. */
       
   186     Dwarf_Global_Context pubnames_context = 0;
       
   187 
       
   188     Dwarf_Half version = 0;
       
   189 
       
   190     /* 
       
   191        Offset from the start of compilation-unit for the current
       
   192        global. */
       
   193     Dwarf_Off die_offset_in_cu = 0;
       
   194 
       
   195     Dwarf_Unsigned global_count = 0;
       
   196 
       
   197     /* Points to the current global read. */
       
   198     Dwarf_Global global = 0;
       
   199 
       
   200     /* 
       
   201        Used to chain the Dwarf_Global_s structs for creating contiguous 
       
   202        list of pointers to the structs. */
       
   203     Dwarf_Chain curr_chain = 0;
       
   204     Dwarf_Chain prev_chain = 0;
       
   205     Dwarf_Chain head_chain = 0;
       
   206 
       
   207     /* Points to contiguous block of Dwarf_Global's to be returned. */
       
   208     Dwarf_Global *ret_globals = 0;
       
   209 
       
   210     /* Temporary counter. */
       
   211     Dwarf_Unsigned i = 0;
       
   212 
       
   213 
       
   214 
       
   215 
       
   216     if (dbg == NULL) {
       
   217 	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
       
   218 	return (DW_DLV_ERROR);
       
   219     }
       
   220     /* We will eventually need the .debug_info data. Load it now. */
       
   221     if (!dbg->de_debug_info) {
       
   222 	int res = _dwarf_load_debug_info(dbg, error);
       
   223 
       
   224 	if (res != DW_DLV_OK) {
       
   225 	    return res;
       
   226 	}
       
   227     }
       
   228 
       
   229     if (section_data_ptr == NULL) {
       
   230 	return (DW_DLV_NO_ENTRY);
       
   231     }
       
   232 
       
   233     pubnames_like_ptr = section_data_ptr;
       
   234     do {
       
   235 	Dwarf_Unsigned length = 0;
       
   236 	int local_extension_size = 0;
       
   237 	int local_length_size = 0;
       
   238 
       
   239 	/* Some compilers emit padding at the end of each cu's area.
       
   240 	   pubnames_ptr_past_end_cu records the true area end for this
       
   241 	   cu's data.  Essentially the length in the header and the 0
       
   242 	   terminator of the data are redundant information. The
       
   243 	   dwarf2/3 spec does not mention what to do if the length is
       
   244 	   past the 0 terminator. So we take any bytes left after the 0 
       
   245 	   as padding and ignore them. */
       
   246 	Dwarf_Small *pubnames_ptr_past_end_cu = 0;
       
   247 
       
   248 
       
   249 	pubnames_context = (Dwarf_Global_Context)
       
   250 	    _dwarf_get_alloc(dbg, context_code, 1);
       
   251 	if (pubnames_context == NULL) {
       
   252 	    _dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   253 	    return (DW_DLV_ERROR);
       
   254 	}
       
   255 	/* READ_AREA_LENGTH updates pubnames_like_ptr for consumed
       
   256 	   bytes */
       
   257 	READ_AREA_LENGTH(dbg, length, Dwarf_Unsigned,
       
   258 			 pubnames_like_ptr, local_length_size,
       
   259 			 local_extension_size);
       
   260 	pubnames_context->pu_length_size = local_length_size;
       
   261 	pubnames_context->pu_extension_size = local_extension_size;
       
   262 	pubnames_context->pu_dbg = dbg;
       
   263 
       
   264 	pubnames_ptr_past_end_cu = pubnames_like_ptr + length;
       
   265 
       
   266 	READ_UNALIGNED(dbg, version, Dwarf_Half,
       
   267 		       pubnames_like_ptr, sizeof(Dwarf_Half));
       
   268 	pubnames_like_ptr += sizeof(Dwarf_Half);
       
   269 	if (version != CURRENT_VERSION_STAMP) {
       
   270 	    _dwarf_error(dbg, error, version_err_num);
       
   271 	    return (DW_DLV_ERROR);
       
   272 	}
       
   273 
       
   274 	/* offset of CU header in debug section */
       
   275 	READ_UNALIGNED(dbg, pubnames_context->pu_offset_of_cu_header,
       
   276 		       Dwarf_Off, pubnames_like_ptr,
       
   277 		       pubnames_context->pu_length_size);
       
   278 	pubnames_like_ptr += pubnames_context->pu_length_size;
       
   279 
       
   280 	FIX_UP_OFFSET_IRIX_BUG(dbg,
       
   281 			       pubnames_context->pu_offset_of_cu_header,
       
   282 			       "pubnames cu header offset");
       
   283 
       
   284 
       
   285 	READ_UNALIGNED(dbg, pubnames_context->pu_info_length,
       
   286 		       Dwarf_Unsigned, pubnames_like_ptr,
       
   287 		       pubnames_context->pu_length_size);
       
   288 	pubnames_like_ptr += pubnames_context->pu_length_size;
       
   289 
       
   290 	if (pubnames_like_ptr > (section_data_ptr + section_length)) {
       
   291 	    _dwarf_error(dbg, error, length_err_num);
       
   292 	    return (DW_DLV_ERROR);
       
   293 	}
       
   294 
       
   295 	/* read initial offset (of DIE within CU) of a pubname, final
       
   296 	   entry is not a pair, just a zero offset */
       
   297 	READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
       
   298 		       pubnames_like_ptr,
       
   299 		       pubnames_context->pu_length_size);
       
   300 	pubnames_like_ptr += pubnames_context->pu_length_size;
       
   301 	FIX_UP_OFFSET_IRIX_BUG(dbg,
       
   302 			       die_offset_in_cu, "offset of die in cu");
       
   303 
       
   304 	/* loop thru pairs. DIE off with CU followed by string */
       
   305 	while (die_offset_in_cu != 0) {
       
   306 
       
   307 	    /* Already read offset, pubnames_like_ptr now points to the 
       
   308 	       string */
       
   309 	    global =
       
   310 		(Dwarf_Global) _dwarf_get_alloc(dbg, global_code, 1);
       
   311 	    if (global == NULL) {
       
   312 		_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   313 		return (DW_DLV_ERROR);
       
   314 	    }
       
   315 	    global_count++;
       
   316 
       
   317 	    global->gl_context = pubnames_context;
       
   318 
       
   319 	    global->gl_named_die_offset_within_cu = die_offset_in_cu;
       
   320 
       
   321 	    global->gl_name = pubnames_like_ptr;
       
   322 
       
   323 	    pubnames_like_ptr = pubnames_like_ptr +
       
   324 		strlen((char *) pubnames_like_ptr) + 1;
       
   325 
       
   326 
       
   327 	    /* finish off current entry chain */
       
   328 	    curr_chain =
       
   329 		(Dwarf_Chain) _dwarf_get_alloc(dbg, DW_DLA_CHAIN, 1);
       
   330 	    if (curr_chain == NULL) {
       
   331 		_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   332 		return (DW_DLV_ERROR);
       
   333 	    }
       
   334 
       
   335 	    /* Put current global on singly_linked list. */
       
   336 	    curr_chain->ch_item = (Dwarf_Global) global;
       
   337 
       
   338 	    if (head_chain == NULL)
       
   339 		head_chain = prev_chain = curr_chain;
       
   340 	    else {
       
   341 		prev_chain->ch_next = curr_chain;
       
   342 		prev_chain = curr_chain;
       
   343 	    }
       
   344 
       
   345 	    /* read offset for the *next* entry */
       
   346 	    READ_UNALIGNED(dbg, die_offset_in_cu, Dwarf_Off,
       
   347 			   pubnames_like_ptr,
       
   348 			   pubnames_context->pu_length_size);
       
   349 
       
   350 	    pubnames_like_ptr += pubnames_context->pu_length_size;
       
   351 	    FIX_UP_OFFSET_IRIX_BUG(dbg,
       
   352 				   die_offset_in_cu,
       
   353 				   "offset of next die in cu");
       
   354 
       
   355 	    if (pubnames_like_ptr > (section_data_ptr + section_length)) {
       
   356 		_dwarf_error(dbg, error, length_err_num);
       
   357 		return (DW_DLV_ERROR);
       
   358 	    }
       
   359 	}
       
   360 	/* ASSERT: die_offset_in_cu == 0 */
       
   361 	if (pubnames_like_ptr > pubnames_ptr_past_end_cu) {
       
   362 	    /* This is some kind of error. This simply cannot happen.
       
   363 	       The encoding is wrong or the length in the header for
       
   364 	       this cu's contribution is wrong. */
       
   365 	    _dwarf_error(dbg, error, length_err_num);
       
   366 	    return (DW_DLV_ERROR);
       
   367 
       
   368 	}
       
   369 	/* If there is some kind of padding at the end of the section,
       
   370 	   as emitted by some compilers, skip over that padding and
       
   371 	   simply ignore the bytes thus passed-over.  With most
       
   372 	   compilers, pubnames_like_ptr == pubnames_ptr_past_end_cu at
       
   373 	   this point */
       
   374 	pubnames_like_ptr = pubnames_ptr_past_end_cu;
       
   375 
       
   376     } while (pubnames_like_ptr < (section_data_ptr + section_length));
       
   377 
       
   378     /* Points to contiguous block of Dwarf_Global's. */
       
   379     ret_globals = (Dwarf_Global *)
       
   380 	_dwarf_get_alloc(dbg, DW_DLA_LIST, global_count);
       
   381     if (ret_globals == NULL) {
       
   382 	_dwarf_error(dbg, error, DW_DLE_ALLOC_FAIL);
       
   383 	return (DW_DLV_ERROR);
       
   384     }
       
   385 
       
   386     /* 
       
   387        Store pointers to Dwarf_Global_s structs in contiguous block,
       
   388        and deallocate the chain. */
       
   389     curr_chain = head_chain;
       
   390     for (i = 0; i < global_count; i++) {
       
   391 	*(ret_globals + i) = curr_chain->ch_item;
       
   392 	prev_chain = curr_chain;
       
   393 	curr_chain = curr_chain->ch_next;
       
   394 	dwarf_dealloc(dbg, prev_chain, DW_DLA_CHAIN);
       
   395     }
       
   396 
       
   397     *globals = ret_globals;
       
   398     *return_count = (Dwarf_Signed) global_count;
       
   399     return DW_DLV_OK;
       
   400 }
       
   401 
       
   402 
       
   403 /*
       
   404 	Given a pubnames entry (or other like section entry)
       
   405 	return thru the ret_name pointer
       
   406 	a pointer to the string which is the entry name.
       
   407 	
       
   408 */
       
   409 int
       
   410 dwarf_globname(Dwarf_Global glob, char **ret_name, Dwarf_Error * error)
       
   411 {
       
   412     if (glob == NULL) {
       
   413 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
       
   414 	return (DW_DLV_ERROR);
       
   415     }
       
   416 
       
   417     *ret_name = (char *) (glob->gl_name);
       
   418     return DW_DLV_OK;
       
   419 }
       
   420 
       
   421 
       
   422 /*
       
   423 	Given a pubnames entry (or other like section entry)
       
   424 	return thru the ret_off pointer the
       
   425 	global offset of the DIE for this entry.
       
   426 	The global offset is the offset within the .debug_info
       
   427 	section as a whole.
       
   428 */
       
   429 int
       
   430 dwarf_global_die_offset(Dwarf_Global global,
       
   431 			Dwarf_Off * ret_off, Dwarf_Error * error)
       
   432 {
       
   433     if (global == NULL) {
       
   434 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
       
   435 	return (DW_DLV_ERROR);
       
   436     }
       
   437 
       
   438     if (global->gl_context == NULL) {
       
   439 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
       
   440 	return (DW_DLV_ERROR);
       
   441     }
       
   442 
       
   443     *ret_off = (global->gl_named_die_offset_within_cu +
       
   444 		global->gl_context->pu_offset_of_cu_header);
       
   445     return DW_DLV_OK;
       
   446 }
       
   447 
       
   448 /*
       
   449 	Given a pubnames entry (or other like section entry)
       
   450 	return thru the ret_off pointer the
       
   451 	offset of the compilation unit header of the
       
   452         compilation unit the global is part of.
       
   453 
       
   454 	In early versions of this, the value returned was
       
   455         the offset of the compilation unit die, and
       
   456 	other cu-local die offsets were faked so adding this to 
       
   457         such a cu-local offset got a true section offset.
       
   458         Now things do as they say (adding *cu_header_offset to
       
   459         a cu-local offset gets the section offset).
       
   460 
       
   461 */
       
   462 int
       
   463 dwarf_global_cu_offset(Dwarf_Global global,
       
   464 		       Dwarf_Off * cu_header_offset,
       
   465 		       Dwarf_Error * error)
       
   466 {
       
   467     Dwarf_Global_Context con = 0;
       
   468 
       
   469     if (global == NULL) {
       
   470 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
       
   471 	return (DW_DLV_ERROR);
       
   472     }
       
   473 
       
   474     con = global->gl_context;
       
   475 
       
   476     if (con == NULL) {
       
   477 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
       
   478 	return (DW_DLV_ERROR);
       
   479     }
       
   480 
       
   481     /* In early libdwarf, this incorrectly returned the offset of the
       
   482        CU DIE. Now correctly returns the header offset. */
       
   483     *cu_header_offset = con->pu_offset_of_cu_header;
       
   484 
       
   485     return DW_DLV_OK;
       
   486 }
       
   487 
       
   488 /*
       
   489   Give back the pubnames entry (or any other like section)
       
   490   name, symbol DIE offset, and the cu-DIE offset.
       
   491 
       
   492   Various errors are possible.
       
   493 
       
   494   The string pointer returned thru ret_name is not
       
   495   dwarf_get_alloc()ed, so no dwarf_dealloc() 
       
   496   DW_DLA_STRING should be applied to it.
       
   497 
       
   498 */
       
   499 int
       
   500 dwarf_global_name_offsets(Dwarf_Global global,
       
   501 			  char **ret_name,
       
   502 			  Dwarf_Off * die_offset,
       
   503 			  Dwarf_Off * cu_die_offset,
       
   504 			  Dwarf_Error * error)
       
   505 {
       
   506     Dwarf_Global_Context con = 0;
       
   507     Dwarf_Debug dbg = 0;
       
   508     Dwarf_Off off = 0;
       
   509 
       
   510     if (global == NULL) {
       
   511 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_NULL);
       
   512 	return (DW_DLV_ERROR);
       
   513     }
       
   514 
       
   515     con = global->gl_context;
       
   516 
       
   517     if (con == NULL) {
       
   518 	_dwarf_error(NULL, error, DW_DLE_GLOBAL_CONTEXT_NULL);
       
   519 	return (DW_DLV_ERROR);
       
   520     }
       
   521 
       
   522     off = con->pu_offset_of_cu_header;
       
   523     /* The offset had better not be too close to the end. If it is,
       
   524        _dwarf_length_of_cu_header() will step off the end and therefore 
       
   525        must not be used. 10 is a meaningless heuristic, but no CU
       
   526        header is that small so it is safe. An erroneous offset is due
       
   527        to a bug in the tool chain. A bug like this has been seen on
       
   528        IRIX with MIPSpro 7.3.1.3 and an executable > 2GB in size and
       
   529        with 2 million pubnames entries. */
       
   530 #define MIN_CU_HDR_SIZE 10
       
   531     dbg = con->pu_dbg;
       
   532     if (dbg == NULL) {
       
   533 	_dwarf_error(NULL, error, DW_DLE_DBG_NULL);
       
   534 	return (DW_DLV_ERROR);
       
   535     }
       
   536     if (dbg->de_debug_info_size &&
       
   537 	((off + MIN_CU_HDR_SIZE) >= dbg->de_debug_info_size)) {
       
   538 	_dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
       
   539 	return (DW_DLV_ERROR);
       
   540     }
       
   541 #undef MIN_CU_HDR_SIZE
       
   542     if (die_offset != NULL) {
       
   543 	*die_offset = global->gl_named_die_offset_within_cu + off;
       
   544     }
       
   545 
       
   546     *ret_name = (char *) global->gl_name;
       
   547 
       
   548     if (cu_die_offset != NULL) {
       
   549 	int res = _dwarf_load_debug_info(dbg, error);
       
   550 
       
   551 	if (res != DW_DLV_OK) {
       
   552 	    return res;
       
   553 	}
       
   554 	/* The offset had better not be too close to the end. If it is, 
       
   555 	   _dwarf_length_of_cu_header() will step off the end and
       
   556 	   therefore must not be used. 10 is a meaningless heuristic,
       
   557 	   but no CU header is that small so it is safe. */
       
   558 	if ((off + 10) >= dbg->de_debug_info_size) {
       
   559 	    _dwarf_error(NULL, error, DW_DLE_OFFSET_BAD);
       
   560 	    return (DW_DLV_ERROR);
       
   561 	}
       
   562 	*cu_die_offset = off + _dwarf_length_of_cu_header(dbg, off);
       
   563     }
       
   564 
       
   565 
       
   566     return DW_DLV_OK;
       
   567 }
       
   568 
       
   569 /*
       
   570 	We have the offset to a CU header.
       
   571 	Return thru outFileOffset the offset of the CU DIE.
       
   572 	
       
   573 	New June, 2001.
       
   574 	Used by SGI debuggers.
       
   575 	No error is possible.
       
   576 */
       
   577 
       
   578 /* ARGSUSED */
       
   579 int
       
   580 dwarf_get_cu_die_offset_given_cu_header_offset(Dwarf_Debug dbg,
       
   581 					       Dwarf_Off
       
   582 					       in_cu_header_offset,
       
   583 					       Dwarf_Off *
       
   584 					       out_cu_die_offset,
       
   585 					       Dwarf_Error * err)
       
   586 {
       
   587     Dwarf_Off len =
       
   588 	_dwarf_length_of_cu_header(dbg, in_cu_header_offset);
       
   589 
       
   590     Dwarf_Off newoff = in_cu_header_offset + len;
       
   591 
       
   592     *out_cu_die_offset = newoff;
       
   593     return DW_DLV_OK;
       
   594 }