From: Timm Bäder
src/readelf.c and libdw/dwarf_getsrclines.c contain the same code to
read header_length, unit_length, minimum_instr_len, etc.
Pull this code out into libdwP.h and into a header_state struct that
goes with the line_state struct in dwarf_getsrclines.c.
Signed-off-by: Timm Bäder
---
libdw/dwarf_getsrclines.c | 172 ---
libdw/libdwP.h| 149 ++
src/readelf.c | 184 +++---
3 files changed, 237 insertions(+), 268 deletions(-)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
index d6a581ad..c54b3bb7 100644
--- a/libdw/dwarf_getsrclines.c
+++ b/libdw/dwarf_getsrclines.c
@@ -96,12 +96,12 @@ struct line_state
};
static inline void
-run_advance_pc (struct line_state *state, unsigned int op_advance,
-uint_fast8_t minimum_instr_len, uint_fast8_t max_ops_per_instr)
+run_advance_pc (struct line_state *state, const struct header_state *header,
+ unsigned int op_advance)
{
- state->addr += minimum_instr_len * ((state->op_index + op_advance)
- / max_ops_per_instr);
- state->op_index = (state->op_index + op_advance) % max_ops_per_instr;
+ state->addr += header->minimum_instr_len * ((state->op_index + op_advance)
+ / header->max_ops_per_instr);
+ state->op_index = (state->op_index + op_advance) % header->max_ops_per_instr;
}
static inline bool
@@ -183,6 +183,8 @@ read_srclines (Dwarf *dbg,
.discriminator = 0
};
+ struct header_state header;
+
/* The dirs normally go on the stack, but if there are too many
we alloc them all. Set up stack storage early, so we can check on
error if we need to free them or not. */
@@ -194,103 +196,14 @@ read_srclines (Dwarf *dbg,
struct dirlist dirstack[MAX_STACK_DIRS];
struct dirlist *dirarray = dirstack;
- if (unlikely (linep + 4 > lineendp))
+ int header_parse_error = header_state_parse (dbg, &header, &linep, &lineendp,
+ address_size);
+ if (header_parse_error != DWARF_E_NOERROR)
{
invalid_data:
__libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
goto out;
}
-
- Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
- unsigned int length = 4;
- if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
-{
- if (unlikely (linep + 8 > lineendp))
- goto invalid_data;
- unit_length = read_8ubyte_unaligned_inc (dbg, linep);
- length = 8;
-}
-
- /* Check whether we have enough room in the section. */
- if (unlikely (unit_length > (size_t) (lineendp - linep)))
-goto invalid_data;
- lineendp = linep + unit_length;
-
- /* The next element of the header is the version identifier. */
- if ((size_t) (lineendp - linep) < 2)
-goto invalid_data;
- uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
- if (unlikely (version < 2) || unlikely (version > 5))
-{
- __libdw_seterrno (DWARF_E_VERSION);
- goto out;
-}
-
- /* DWARF5 explicitly lists address and segment_selector sizes. */
- if (version >= 5)
-{
- if ((size_t) (lineendp - linep) < 2)
- goto invalid_data;
- size_t line_address_size = *linep++;
- size_t segment_selector_size = *linep++;
- if (line_address_size != address_size || segment_selector_size != 0)
- goto invalid_data;
-}
-
- /* Next comes the header length. */
- Dwarf_Word header_length;
- if (length == 4)
-{
- if ((size_t) (lineendp - linep) < 4)
- goto invalid_data;
- header_length = read_4ubyte_unaligned_inc (dbg, linep);
-}
- else
-{
- if ((size_t) (lineendp - linep) < 8)
- goto invalid_data;
- header_length = read_8ubyte_unaligned_inc (dbg, linep);
-}
- const unsigned char *header_start = linep;
-
- /* Next the minimum instruction length. */
- uint_fast8_t minimum_instr_len = *linep++;
-
- /* Next the maximum operations per instruction, in version 4 format. */
- uint_fast8_t max_ops_per_instr = 1;
- if (version >= 4)
-{
- if (unlikely ((size_t) (lineendp - linep) < 1))
- goto invalid_data;
- max_ops_per_instr = *linep++;
- if (unlikely (max_ops_per_instr == 0))
- goto invalid_data;
-}
-
- /* 4 more bytes, is_stmt, line_base, line_range and opcode_base. */
- if ((size_t) (lineendp - linep) < 4)
-goto invalid_data;
-
- /* Then the flag determining the default value of the is_stmt
- register. */
- uint_fast8_t default_is_stmt = *linep++;
-
- /* Now the line base. */
- int_fast8_t line_base = (int8_t) *linep++;
-
- /* And the line range. */
- uint_fast8_t line_range = *linep++;
-
- /* The opcode base. */
- uint_fast8_t opcode_base = *linep++;
-
- /* Remember array with the standard opcode length (-1 to account for
- the opcode with value zero not being mentioned). */
- cons