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