BDE 4.14.0 Production release
Loading...
Searching...
No Matches
balst_resolver_dwarfreader.h
Go to the documentation of this file.
1/// @file balst_resolver_dwarfreader.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// balst_resolver_dwarfreader.h -*-C++-*-
8
9#ifndef INCLUDED_BALST_RESOLVER_DWARFREADER
10#define INCLUDED_BALST_RESOLVER_DWARFREADER
11
12#include <bsls_ident.h>
13BSLS_IDENT("$Id: $")
14
15/// @defgroup balst_resolver_dwarfreader balst_resolver_dwarfreader
16/// @brief Provide mechanism for reading DWARF information from object files.
17/// @addtogroup bal
18/// @{
19/// @addtogroup balst
20/// @{
21/// @addtogroup balst_resolver_dwarfreader
22/// @{
23///
24/// <h1> Outline </h1>
25/// * <a href="#balst_resolver_dwarfreader-purpose"> Purpose</a>
26/// * <a href="#balst_resolver_dwarfreader-classes"> Classes </a>
27/// * <a href="#balst_resolver_dwarfreader-description"> Description </a>
28/// * <a href="#balst_resolver_dwarfreader-usage"> Usage </a>
29///
30/// # Purpose {#balst_resolver_dwarfreader-purpose}
31/// Provide mechanism for reading DWARF information from object files.
32///
33/// # Classes {#balst_resolver_dwarfreader-classes}
34///
35/// - balst::Resolver_DwarfReader: reading mechanism
36///
37/// @see balst_resolverimpl_elf
38/// balst_resolver_filehelper
39///
40/// # Description {#balst_resolver_dwarfreader-description}
41/// This component provides a class,
42/// `balst::Resolver_DwarfReader`, that is optimized for reading
43/// information from object files that are in the DWARF format. The Elf object
44/// file format is used on Linux and Solaris platforms, and the DWARF file
45/// format is used within ELF files to encode source file name and line number
46/// information. The Elf format is described by documents at:
47/// * `http://en.wikipedia.org/wiki/Executable_and_Linkable_Format`
48/// * `http://downloads.openwatcom.org/ftp/devel/docs/elf-64-gen.pdf`
49/// * `http://www.sco.com/developers/gabi/latest/contents.html`
50/// The DWARF format is described by documents at:
51/// * `http://dwarfstd.org`
52///
53/// Note that this file does not include everything necessary to resolve DWARF
54/// information. Most of that functionality is in
55/// `balst_resolverimpl_elf`, and this component only describe a tool
56/// used within that effort.
57///
58/// ## Usage {#balst_resolver_dwarfreader-usage}
59///
60///
61/// This component is an implementation detail of `balst` and is *not* intended
62/// for direct client use. It is subject to change without notice. As such, a
63/// usage example is not provided.
64/// @}
65/** @} */
66/** @} */
67
68/** @addtogroup bal
69 * @{
70 */
71/** @addtogroup balst
72 * @{
73 */
74/** @addtogroup balst_resolver_dwarfreader
75 * @{
76 */
77
78#include <balscm_version.h>
79
82
83#include <bdlb_bitutil.h>
84
85#include <bdls_filesystemutil.h>
86
87#include <bslmf_assert.h>
88
89#include <bsls_assert.h>
90#include <bsls_platform.h>
91#include <bsls_review.h>
92#include <bsls_types.h>
93
94#include <bsl_cstddef.h>
95#include <bsl_cstring.h>
96#include <bsl_string.h>
97
98
99namespace balst {
100
101#if defined(BALST_OBJECTFILEFORMAT_RESOLVER_DWARF)
102
103 // ==========================
104 // class Resolver_DwarfReader
105 // ==========================
106
107class Resolver_DwarfReader {
108 public:
109 // PUBLIC TYPES
110 typedef bdls::FilesystemUtil::Offset Offset;
111 typedef bsls::Types::UintPtr UintPtr;
112 typedef bsls::Types::IntPtr IntPtr;
113 typedef bsls::Types::Uint64 Uint64;
114
115 struct Section {
116 // Refers to one section of a segment.
117
118 // DATA
119 Offset d_offset; // offset of the section in the file
120 Offset d_size; // size of that section in bytes
121
122 // CREATOR
123 Section();
124 // Create a zero-value 'Section' object.
125
126 // MANIPULATOR
127 void reset(Offset offset = 0, Offset size = 0);
128 // Reset this 'Section' object to have the specified 'offset' and
129 // the specified 'size'.
130 };
131
132 // PUBLIC CONSTANTS
133 enum { k_SCRATCH_BUF_LEN = 32 * 1024 - 64 };
134 // length in bytes of d_buffer_p; 32K minus a little so we don't
135 // waste a page
136
137 // DWARF enums
138
139 // The DWARF documents are at: http://www.dwarfstd.org/Download.php.
140 //
141 // The DWARF specs specify no 'struct's, only several hundred identifiers
142 // of the form 'DW_*' defining integer values. Some sources provide
143 // include files 'dwarf.h' specifying 'enum's for all these values, but
144 // accessing these include files from DPKG proved problematic, and the
145 // versions available only provided DWARF 3 identifiers and we needed some
146 // DWARF 4 id's too. The 'dwarf.h' available from Red Hat was LGPL'ed,
147 // posing potential licensing problems with copying or cut/pasting it into
148 // the BDE code base, which is licensed more permissively than LGPL.
149 //
150 // The simplest approach was to implement these enums directly copying them
151 // from the spec. The following are a subset of all the id's in the spec,
152 // limited to the ones we use in this package.
153 //
154 // Rather than name the enum's 'DW_*' as they appear in the spec, we name
155 // them 'e_DW_*' according to BDE convention.
156
157 enum Dwarf3Enums {
158 // These values were obtained from the DWARF 3 Spec.
159
160 e_DW_AT_sibling = 0x01,
161 e_DW_AT_location = 0x02,
162 e_DW_AT_name = 0x03,
163 e_DW_AT_ordering = 0x09,
164 e_DW_AT_byte_size = 0x0b,
165 e_DW_AT_bit_offset = 0x0c,
166 e_DW_AT_bit_size = 0x0d,
167 e_DW_AT_stmt_list = 0x10,
168 e_DW_AT_low_pc = 0x11,
169 e_DW_AT_high_pc = 0x12,
170 e_DW_AT_language = 0x13,
171 e_DW_AT_discr = 0x15,
172 e_DW_AT_discr_value = 0x16,
173 e_DW_AT_visibility = 0x17,
174 e_DW_AT_import = 0x18,
175 e_DW_AT_string_length = 0x19,
176 e_DW_AT_common_reference = 0x1a,
177 e_DW_AT_comp_dir = 0x1b,
178 e_DW_AT_const_value = 0x1c,
179 e_DW_AT_containing_type = 0x1d,
180 e_DW_AT_default_value = 0x1e,
181 e_DW_AT_inline = 0x20,
182 e_DW_AT_is_optional = 0x21,
183 e_DW_AT_lower_bound = 0x22,
184 e_DW_AT_producer = 0x25,
185 e_DW_AT_prototyped = 0x27,
186 e_DW_AT_return_addr = 0x2a,
187 e_DW_AT_start_scope = 0x2c,
188 e_DW_AT_bit_stride = 0x2e,
189 e_DW_AT_upper_bound = 0x2f,
190 e_DW_AT_abstract_origin = 0x31,
191 e_DW_AT_accessibility = 0x32,
192 e_DW_AT_address_class = 0x33,
193 e_DW_AT_artificial = 0x34,
194 e_DW_AT_base_types = 0x35,
195 e_DW_AT_calling_convention = 0x36,
196 e_DW_AT_count = 0x37,
197 e_DW_AT_data_member_location = 0x38,
198 e_DW_AT_decl_column = 0x39,
199 e_DW_AT_decl_file = 0x3a,
200 e_DW_AT_decl_line = 0x3b,
201 e_DW_AT_declaration = 0x3c,
202 e_DW_AT_discr_list = 0x3d,
203 e_DW_AT_encoding = 0x3e,
204 e_DW_AT_external = 0x3f,
205 e_DW_AT_frame_base = 0x40,
206 e_DW_AT_friend = 0x41,
207 e_DW_AT_identifier_case = 0x42,
208 e_DW_AT_macro_info = 0x43,
209 e_DW_AT_namelist_item = 0x44,
210 e_DW_AT_priority = 0x45,
211 e_DW_AT_segment = 0x46,
212 e_DW_AT_specification = 0x47,
213 e_DW_AT_static_link = 0x48,
214 e_DW_AT_type = 0x49,
215 e_DW_AT_use_location = 0x4a,
216 e_DW_AT_variable_parameter = 0x4b,
217 e_DW_AT_virtuality = 0x4c,
218 e_DW_AT_vtable_elem_location = 0x4d,
219 e_DW_AT_allocated = 0x4e,
220 e_DW_AT_associated = 0x4f,
221 e_DW_AT_data_location = 0x50,
222 e_DW_AT_byte_stride = 0x51,
223 e_DW_AT_entry_pc = 0x52,
224 e_DW_AT_use_UTF8 = 0x53,
225 e_DW_AT_extension = 0x54,
226 e_DW_AT_ranges = 0x55,
227 e_DW_AT_trampoline = 0x56,
228 e_DW_AT_call_column = 0x57,
229 e_DW_AT_call_file = 0x58,
230 e_DW_AT_call_line = 0x59,
231 e_DW_AT_description = 0x5a,
232 e_DW_AT_binary_scale = 0x5b,
233 e_DW_AT_decimal_scale = 0x5c,
234 e_DW_AT_small = 0x5d,
235 e_DW_AT_decimal_sign = 0x5e,
236 e_DW_AT_digit_count = 0x5f,
237 e_DW_AT_picture_string = 0x60,
238 e_DW_AT_mutable = 0x61,
239 e_DW_AT_threads_scaled = 0x62,
240 e_DW_AT_explicit = 0x63,
241 e_DW_AT_object_pointer = 0x64,
242 e_DW_AT_endianity = 0x65,
243 e_DW_AT_elemental = 0x66,
244 e_DW_AT_pure = 0x67,
245 e_DW_AT_recursive = 0x68,
246
247 e_DW_CHILDREN_no = 0x00,
248 e_DW_CHILDREN_yes = 0x01,
249
250 e_DW_FORM_addr = 0x01,
251 e_DW_FORM_block2 = 0x03,
252 e_DW_FORM_block4 = 0x04,
253 e_DW_FORM_data2 = 0x05,
254 e_DW_FORM_data4 = 0x06,
255 e_DW_FORM_data8 = 0x07,
256 e_DW_FORM_string = 0x08,
257 e_DW_FORM_block = 0x09,
258 e_DW_FORM_block1 = 0x0a,
259 e_DW_FORM_data1 = 0x0b,
260 e_DW_FORM_flag = 0x0c,
261 e_DW_FORM_sdata = 0x0d,
262 e_DW_FORM_strp = 0x0e,
263 e_DW_FORM_udata = 0x0f,
264 e_DW_FORM_ref_addr = 0x10,
265 e_DW_FORM_ref1 = 0x11,
266 e_DW_FORM_ref2 = 0x12,
267 e_DW_FORM_ref4 = 0x13,
268 e_DW_FORM_ref8 = 0x14,
269 e_DW_FORM_ref_udata = 0x15,
270 e_DW_FORM_indirect = 0x16,
271 e_DW_FORM_line_strp = 0x1f,
272
273 e_DW_INL_declared_inlined = 0x03,
274
275 e_DW_LNCT_path = 0x01,
276 e_DW_LNCT_directory_index = 0x02,
277 e_DW_LNCT_timestamp = 0x03,
278 e_DW_LNCT_size = 0x04,
279 e_DW_LNCT_MD5 = 0x05,
280 e_DW_LNCT_lo_user = 0x2000,
281 e_DW_LNCT_hi_user = 0x3fff,
282
283 e_DW_LNE_end_sequence = 0x01,
284 e_DW_LNE_set_address = 0x02,
285 e_DW_LNE_define_file = 0x03,
286
287 e_DW_LNS_copy = 0x01,
288 e_DW_LNS_advance_pc = 0x02,
289 e_DW_LNS_advance_line = 0x03,
290 e_DW_LNS_set_file = 0x04,
291 e_DW_LNS_set_column = 0x05,
292 e_DW_LNS_negate_stmt = 0x06,
293 e_DW_LNS_set_basic_block = 0x07,
294 e_DW_LNS_const_add_pc = 0x08,
295 e_DW_LNS_fixed_advance_pc = 0x09,
296 e_DW_LNS_set_prologue_end = 0x0a,
297 e_DW_LNS_set_epilogue_begin = 0x0b,
298 e_DW_LNS_set_isa = 0x0c,
299
300 e_DW_TAG_array_type = 0x01,
301 e_DW_TAG_class_type = 0x02,
302 e_DW_TAG_entry_point = 0x03,
303 e_DW_TAG_enumeration_type = 0x04,
304 e_DW_TAG_formal_parameter = 0x05,
305 e_DW_TAG_imported_declaration = 0x08,
306 e_DW_TAG_label = 0x0a,
307 e_DW_TAG_lexical_block = 0x0b,
308 e_DW_TAG_member = 0x0d,
309 e_DW_TAG_pointer_type = 0x0f,
310 e_DW_TAG_reference_type = 0x10,
311 e_DW_TAG_compile_unit = 0x11,
312 e_DW_TAG_string_type = 0x12,
313 e_DW_TAG_structure_type = 0x13,
314 e_DW_TAG_subroutine_type = 0x15,
315 e_DW_TAG_typedef = 0x16,
316 e_DW_TAG_union_type = 0x17,
317 e_DW_TAG_unspecified_parameters = 0x18,
318 e_DW_TAG_variant = 0x19,
319 e_DW_TAG_common_block = 0x1a,
320 e_DW_TAG_common_inclusion = 0x1b,
321 e_DW_TAG_inheritance = 0x1c,
322 e_DW_TAG_inlined_subroutine = 0x1d,
323 e_DW_TAG_module = 0x1e,
324 e_DW_TAG_ptr_to_member_type = 0x1f,
325 e_DW_TAG_set_type = 0x20,
326 e_DW_TAG_subrange_type = 0x21,
327 e_DW_TAG_with_stmt = 0x22,
328 e_DW_TAG_access_declaration = 0x23,
329 e_DW_TAG_base_type = 0x24,
330 e_DW_TAG_catch_block = 0x25,
331 e_DW_TAG_const_type = 0x26,
332 e_DW_TAG_constant = 0x27,
333 e_DW_TAG_enumerator = 0x28,
334 e_DW_TAG_file_type = 0x29,
335 e_DW_TAG_friend = 0x2a,
336 e_DW_TAG_namelist = 0x2b,
337 e_DW_TAG_namelist_item = 0x2c,
338 e_DW_TAG_packed_type = 0x2d,
339 e_DW_TAG_subprogram = 0x2e,
340 e_DW_TAG_template_type_parameter = 0x2f,
341 e_DW_TAG_template_value_parameter = 0x30,
342 e_DW_TAG_thrown_type = 0x31,
343 e_DW_TAG_try_block = 0x32,
344 e_DW_TAG_variant_part = 0x33,
345 e_DW_TAG_variable = 0x34,
346 e_DW_TAG_volatile_type = 0x35,
347 e_DW_TAG_dwarf_procedure = 0x36,
348 e_DW_TAG_restrict_type = 0x37,
349 e_DW_TAG_interface_type = 0x38,
350 e_DW_TAG_namespace = 0x39,
351 e_DW_TAG_imported_module = 0x3a,
352 e_DW_TAG_unspecified_type = 0x3b,
353 e_DW_TAG_partial_unit = 0x3c,
354 e_DW_TAG_imported_unit = 0x3d,
355 e_DW_TAG_condition = 0x3f,
356 e_DW_TAG_shared_type = 0x40,
357 e_DW_TAG_lo_user = 0x4080,
358 e_DW_TAG_hi_user = 0xffff
359 };
360
361 enum Dwarf4Enums {
362 // These values were obtained from the DWARF 4 Spec.
363
364 e_DW_AT_signature = 0x69,
365 e_DW_AT_main_subprogram = 0x6a,
366 e_DW_AT_data_bit_offset = 0x6b,
367 e_DW_AT_const_expr = 0x6c,
368 e_DW_AT_enum_class = 0x6d,
369 e_DW_AT_linkage_name = 0x6e,
370 e_DW_AT_lo_user = 0x2000,
371 e_DW_AT_hi_user = 0x3fff,
372
373 e_DW_FORM_sec_offset = 0x17,
374 e_DW_FORM_exprloc = 0x18,
375 e_DW_FORM_flag_present = 0x19,
376 e_DW_FORM_ref_sig8 = 0x20,
377
378 e_DW_LNE_set_discriminator = 0x04,
379
380 e_DW_TAG_mutable_type = 0x3e,
381 e_DW_TAG_type_unit = 0x41,
382 e_DW_TAG_rvalue_reference_type = 0x42,
383 e_DW_TAG_template_alias = 0x43
384 };
385
386 enum Dwarf5Enums {
387 e_DW_UT_compile = 0x1,
388 e_DW_UT_type = 0x2,
389 e_DW_UT_partial = 0x3,
390 e_DW_UT_skeleton = 0x4,
391 e_DW_UT_split_compile = 0x5,
392 e_DW_UT_split_type = 0x6,
393 e_DW_UT_lo_user = 0x80,
394 e_DW_UT_hi_user = 0xff
395 };
396
397 private:
398 // DATA
399 balst::Resolver_FileHelper *d_helper_p; // filehelper for current
400 // segment
401
402 char *d_buffer_p; // buffer.
403 // k_SCRATCH_BUF_LEN long
404
405 Offset d_offset; // offset last read from
406
407 Offset d_beginOffset; // beg of current section
408
409 Offset d_endOffset; // end of current section
410
411 const char *d_readPtr; // current place to read
412 // from (in the buffer)
413
414 const char *d_endPtr; // end of what's in buffer
415
416 int d_offsetSize; // offset size determined
417 // by 'readInitalLength'
418
419 int d_addressSize; // address read by
420 // 'getAddress' or set by
421 // 'setAddressSize'.
422
423 private:
424 // NOT IMPLEMENTED
425 Resolver_DwarfReader(const Resolver_DwarfReader&);
426 Resolver_DwarfReader& operator=(const Resolver_DwarfReader&);
427
428 private:
429 // PRIVATE MANIPULATORS
430
431 /// Determine if we are able to read the specified `numBytes` from
432 /// `d_buffer`. If not, `reload` is used to attempt to accomodate this
433 /// `needBytes` request. Return 0 if we are able to read `numBytes`
434 /// from `d_buffer` after this invocation of `needBytes`, and a non-zero
435 /// value otherwise.
436 int needBytes(bsl::size_t numBytes);
437
438 /// Reload the buffer to accomodate a read of at least the specified
439 /// `numBytes`. If possible, read up to the end of the section or the
440 /// size of the buffer, whichever is shorter. Return 0 on success, and
441 /// a non-zero value otherwise.
442 int reload(bsl::size_t numBytes);
443
444 public:
445 // CLASS METHODS
446 static
447 const char *stringForAt(unsigned id);
448 // Return the string equivalent of the specified 'e_DW_AT_*' 'id'.
449
450 static
451 const char *stringForForm(unsigned id);
452 // Return the string equivalent of the specified 'e_DW_FORM_*' 'id'.
453
454 static
455 const char *stringForInlineState(unsigned inlineState);
456 // Return the string equivalent of the specified 'e_DW_INL_*'
457 // 'inlineState'.
458
459 static
460 const char *stringForLNCT(unsigned id);
461 // Return the string equivalent of the specified 'e_DW_LNCT_*' 'id'.
462
463 static
464 const char *stringForLNE(unsigned id);
465 // Return the string equivalent of the specified 'e_DW_LNE_*' 'id'.
466
467 static
468 const char *stringForLNS(unsigned id);
469 // Return the string equivalent of the specified 'e_DW_LNS_*' 'id'.
470
471 static
472 const char *stringForTag(unsigned tag);
473 // Return the string equivalent of the specified 'e_DW_TAG_*' 'tag'.
474
475 // CREATORS
476
477 /// Create a `Reader` object in a null state.
478 Resolver_DwarfReader();
479
480 /// Destroy this object.
481 ~Resolver_DwarfReader() = default;
482
483 // MANIPULATORS
484
485 /// Disable this object for further use.
486 void disable();
487
488 /// Initialize this `Reader` object using the specified `fileHelper` and
489 /// the specified `buffer`, to operate on the specified `section`, where
490 /// the specified `libraryFileSize` is the size of the library or
491 /// executable file. `buffer` is assumed to be at least
492 /// `k_SCRATCH_BUF_LEN` long.
493 int init(balst::Resolver_FileHelper *fileHelper,
494 char *buffer,
495 const Section& section,
496 Offset libraryFileSize);
497
498 /// Read to the specified `dst`. This function will fail if
499 /// `d_addressSize` has not been initialized by `readAddressSize` or
500 /// `setAddressSize`. Return 0 on success and a non-zero value
501 /// otherwise.
502 int readAddress(UintPtr *dst);
503
504 /// Read to the specified `dst` according to the specified `form`.
505 /// Return 0 on success and a non-zero value otherwise.
506 int readAddress(UintPtr *dst, unsigned form);
507
508 /// Read the address size from a single unsigned byte, check it, and
509 /// assign `d_addressSize` to it. Return 0 on success and a non-zero
510 /// value otherwise. It is an error if address size is not equal to the
511 /// size of an `unsigned int` or of a `void *`.
512 int readAddressSize();
513
514 /// Read the initial length of the object according to the DWARF
515 /// specification to the specified `*dst`, which is an 8-byte value.
516 /// Read `*dst` first as a 4 byte value, setting the high-order 4 bytes
517 /// to 0, and if the value is below 0xfffffff0, then that indicates that
518 /// section offsets are to be read as 4 byte values within the object
519 /// whose length is specified. If the value is 0xffffffff, read the
520 /// next 8 bytes into `*dst` and that indicates that section offsets are
521 /// to be 8 bytes within the object whose length is specified.
522 /// Initialize `d_offsetSize` accordingly. Values in the range
523 /// `[0xfffffff0, 0xffffffff)` are illegal for that first 4 bytes.
524 /// Return 0 on success and a non-zero value otherwise. Note that when
525 /// we read a 4-byte value, we do not extend sign to the high order 4
526 /// bytes of `*dst`.
527 int readInitialLength(Offset *dst);
528
529 /// Read a signed, variable-length number into the specified `*dst`.
530 /// Return 0 on success and a non-zero value otherwise.
531 template <class TYPE>
532 int readLEB128(TYPE *dst);
533
534 /// Read an unsigned, variable-length number into the specified `*dst`.
535 /// Return 0 on success and a non-zero value otherwise.
536 template <class TYPE>
537 int readULEB128(TYPE *dst);
538
539 /// Read to the specified `*dst`, where the specified `offsetSize` is the
540 /// number of low-order bytes to be read into the offset, where `*dst` is 8
541 /// bytes, and extra high-order bytes are to be set to 0. Do not extend
542 /// sign. Return 0 on success and a non-zero value otherwise.
543 int readOffset(Offset *dst,
544 bsl::size_t offsetSize);
545
546 /// Read to the specified `*dst` according to the specified `form`, where
547 /// `form` is a DWARF enum of the `e_DW_FORM_*` category. Return 0 on
548 /// success and a non-zero value otherwise.
549 int readOffsetFromForm(Offset *dst,
550 unsigned form);
551
552 /// Read to the specified offset `*dst` according to `d_offsetSize`.
553 /// Return 0 on success and a non-zero value otherwise. Note that when
554 /// the offset read is only 4 bytes, no sign extension takes place as
555 /// we always expect a positive result.
556 int readSectionOffset(Offset *dst);
557
558 /// Read a null-terminated string to the specified `*dst`. If no `dst`
559 /// is specified, skip over the string without copying it. This
560 /// function will fail if the string length is greater than
561 /// `k_SCRATCH_BUFFER_LEN - 1`.
562 int readString(bsl::string *dst = 0);
563
564 /// Read a null terminated string to the specified `*dst` from the
565 /// specified `offset` plus `d_beginOffset`. Note that, unlike most of
566 /// the other `read` functions, this one is intended for random access
567 /// so does not read a full buffer ahead, instead reading a fairly
568 /// minimal amount of data near the specified location.
569 int readStringAt(bsl::string *dst, Offset offset);
570
571 /// Read to the specified string either from the current reader (if the
572 /// specified `form` is `e_DW_FORM_string`) or read an offset from the
573 /// current reader, then use that to read the string either from the
574 /// specified `*strReader` (if `form` is `e_DW_FORM_strp`) or from the
575 /// specified `*lineStrReader` (if `form` is `e_DW_FORM_line_strp`).
576 /// Return 0 on success and a non-zero value otherwise.
577 int readStringFromForm(bsl::string *dst,
578 Resolver_DwarfReader *strReader,
579 Resolver_DwarfReader *lineStrReader,
580 unsigned form);
581
582 /// Read a value into the specified `*dst`, assuming that it is represented
583 /// by `sizeof(*dst)` bytes.
584 template <class TYPE>
585 int readValue(TYPE *dst);
586
587 /// Explicitly set the `d_addressSize` of this reader to the specified
588 /// `size`. This function will fail unless the size is the
589 /// `sizeof(unsigned) == size` or `sizeof(UintPtr) == size`.
590 int setAddressSize(unsigned size);
591
592 /// Set the end offset to the specified `newOffset`.
593 int setEndOffset(Offset newOffset);
594
595 /// Skip forward over the specified `bytes` without reading them.
596 int skipBytes(Offset bytes);
597
598 /// Skip over a null terminated string without copying it.
599 int skipString();
600
601 /// Skip over data according to the specified `form`, which is an enum
602 /// of type `e_DW_FORM_*`.
603 int skipForm(unsigned form);
604
605 /// Skip to the specified `offset`, which must be in the section associated
606 /// with this reader. Return 0 on success and a non-zero value otherwise.
607 int skipTo(Offset offset);
608
609 /// Skip a variable-length integer. Note this will work for both
610 /// LEB128's and ULEB128's.
611 int skipULEB128();
612
613 // ACCESSORS
614
615 /// Return the address size field.
616 int addressSize() const;
617
618 /// Return `true` if the reader has reached the end of the section and
619 /// `false` otherwise.
620 bool atEndOfSection() const;
621
622 /// Return the current offset taking the `d_reader` position into account.
623 Offset offset() const;
624
625 /// Return the offset length that was set by the `readInitialLength`
626 /// function.
627 Offset offsetSize() const;
628
629 /// Return `false` if this reader is disabled and `true` otherwise.
630 bool isEnabled() const;
631};
632
633// PRIVATE MANIPULATORS
634inline
635int Resolver_DwarfReader::needBytes(bsl::size_t numBytes)
636{
637 IntPtr diff = d_endPtr - d_readPtr;
638
639 if (diff < static_cast<IntPtr>(numBytes)) {
640 BSLS_ASSERT(0 <= diff);
641
642 return reload(numBytes); // RETURN
643 }
644
645 return 0;
646}
647
648template <class TYPE>
649int Resolver_DwarfReader::readLEB128(TYPE *dst) // DWARF doc 7.6
650{
651 BSLMF_ASSERT(static_cast<TYPE>(-1) < 0); // 'TYPE' must be signed
652
653 int rc;
654
655 Uint64 tmpDst = 0;
656
657 unsigned char u = 0x80;
658
659 enum { k_MAX_SHIFT = sizeof(*dst) * 8 };
660
661 unsigned shift = -7;
662 do {
663 rc = readValue(&u);
664 if (rc) {
665 // Assign to '*dst' to silence the confused optimizer complaining
666 // about 'maybe used before set' in caller.
667
668 *dst = 0;
669 return -1; // RETURN
670 }
671
672 const Uint64 masked = 0x7f & u;
673 shift += 7;
674 tmpDst |= masked << shift;
675 } while (0x80 & u);
676
677 if (static_cast<TYPE>(-1) < 0) {
678 // signed type, extend sign
679
680 const Uint64 negFlag = static_cast<Uint64>(0x40) << shift;
681 if (negFlag & tmpDst) {
682 tmpDst |= ~(negFlag - 1);
683 }
684 }
685
686 *dst = static_cast<TYPE>(tmpDst);
687
688 return 0;
689}
690
691template <class TYPE>
692int Resolver_DwarfReader::readULEB128(TYPE *dst) // DWARF doc 7.6
693{
694 Uint64 tmpDst = 0;
695
696 unsigned char u = 0x80;
697
698 unsigned shift = 0;
699 for (; (0x80 & u); shift += 7) {
700 int rc = readValue(&u);
701 if (0 != rc) {
702 // Assign to '*dst' to silence the confused optimizer complaining
703 // about 'maybe used before set' in caller.
704
705 *dst = 0;
706 return -1; // RETURN
707 }
708
709 const Uint64 masked = 0x7f & u;
710 tmpDst |= masked << shift;
711 }
712#if defined(BSLS_ASSERT_LEVEL_ASSERT_SAFE)
713 if (shift >= sizeof(*dst) * 8 + 7) {
714 // Assign to '*dst' to silence the confused optimizer complaining about
715 // 'maybe used before set' in caller.
716
717 *dst = 0;
718 return -1; // RETURN
719 }
720#endif
721
722 *dst = static_cast<TYPE>(tmpDst);
723
724 return 0;
725}
726
727template <class TYPE>
728inline
729int Resolver_DwarfReader::readValue(TYPE *dst)
730{
731 int rc = needBytes(sizeof(*dst));
732 if (rc) {
733 // Assign to '*dst' to silence the confused optimizer complaining about
734 // 'maybe used before set' in caller.
735
736 *dst = 0;
737 return -1; // RETURN
738 }
739
740 bsl::memcpy(dst, d_readPtr, sizeof(*dst));
741 d_readPtr += sizeof(*dst);
742
743 return 0;
744}
745
746inline
747int Resolver_DwarfReader::skipBytes(Offset bytes)
748{
749 BSLS_ASSERT(bytes >= 0);
750
751 if (bytes > d_endPtr - d_readPtr) {
752 Offset off = offset();
753
754 if (off < d_beginOffset) {
755 return -1; // RETURN
756 }
757 if (off + bytes > d_endOffset) {
758 return -1; // RETURN
759 }
760
761 // By setting 'd_readPtr == d_endPtr' we guarantee that the next read
762 // will trigger a reload.
763
764 d_offset += bytes + (d_readPtr - d_buffer_p);
765 d_readPtr = d_buffer_p;
766 d_endPtr = d_readPtr;
767 }
768 else {
769 d_readPtr += bytes;
770 }
771
772 return 0;
773}
774
775inline
776int Resolver_DwarfReader::skipString()
777{
778 do {
779 int rc = needBytes(1);
780 if (rc) {
781 return -1; // RETURN
782 }
783 } while (*d_readPtr++);
784
785 return 0;
786}
787
788// ACCESSORS
789inline
790int Resolver_DwarfReader::addressSize() const
791{
792 return d_addressSize;
793}
794
795inline
796bool Resolver_DwarfReader::atEndOfSection() const
797{
798 return d_readPtr == d_endPtr &&
799 d_endOffset - d_offset == d_readPtr - d_buffer_p;
800}
801
802inline
803Resolver_DwarfReader::Offset
804Resolver_DwarfReader::offset() const
805{
806 return d_offset + (d_readPtr - d_buffer_p);
807}
808
809inline
810Resolver_DwarfReader::Offset
811Resolver_DwarfReader::offsetSize() const
812{
813 return d_offsetSize;
814}
815
816inline
817bool Resolver_DwarfReader::isEnabled() const
818{
819 return 0 != d_buffer_p;
820}
821
822#endif
823
824} // close package namespace
825
826
827#endif
828
829// ----------------------------------------------------------------------------
830// Copyright 2016 Bloomberg Finance L.P.
831//
832// Licensed under the Apache License, Version 2.0 (the "License");
833// you may not use this file except in compliance with the License.
834// You may obtain a copy of the License at
835//
836// http://www.apache.org/licenses/LICENSE-2.0
837//
838// Unless required by applicable law or agreed to in writing, software
839// distributed under the License is distributed on an "AS IS" BASIS,
840// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
841// See the License for the specific language governing permissions and
842// limitations under the License.
843// ----------------------------- END-OF-FILE ----------------------------------
844
845/** @} */
846/** @} */
847/** @} */
Definition bslstl_string.h:1281
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_ASSERT(X)
Definition bsls_assert.h:1804
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition balst_objectfileformat.h:161
void reset(TYPE *object)
Reset the value of the specified object to its default value.
std::size_t UintPtr
Definition bsls_types.h:126
unsigned long long Uint64
Definition bsls_types.h:137
std::ptrdiff_t IntPtr
Definition bsls_types.h:130