/* Attribute value. */
uint64_t value;
+ read_ctx block;
+
storage_class_t storclass = form->storage_class ();
- if (storclass == sc_string)
+ if (!read_generic_value (ctx, form->width (cu), storclass,
+ &where, &value, &block))
{
- if (!read_ctx_read_str (ctx))
- goto cant_read;
+ // Note that for fw_uleb and fw_sleb we report the
+ // error the second time now.
+ wr_error (where)
+ << "can't read value of attribute "
+ << *attribute << '.' << std::endl;
+ return -1;
}
- else
+ if (storclass == sc_block)
{
- if (!read_sc_value (&value, form->width (cu), ctx, &where))
- {
- // Note that for fw_uleb and fw_sleb we report the
- // error the second time now.
- cant_read:
- wr_error (where)
- << "can't read value of attribute "
- << *attribute << '.' << std::endl;
- return -1;
- }
-
- if (storclass == sc_block)
+ if (cls == cl_exprloc)
{
- // Read & validate the block body.
- if (cls == cl_exprloc)
- {
- uint64_t expr_start
- = cu->head->offset + read_ctx_get_offset (ctx);
- if (!check_location_expression
- (file, ctx, cu, expr_start, reloc, value, &where))
- return false;
- }
- else
- relocation_skip (reloc,
- read_ctx_get_offset (ctx) + value,
- &where, skip_mismatched);
-
- if (!read_ctx_skip (ctx, value))
- goto cant_read;
+ uint64_t expr_start
+ = cu->head->offset + read_ctx_get_offset (ctx) - value;
+ if (!check_location_expression
+ (ver, file, &block, cu,
+ expr_start, reloc, value, &where))
+ return false;
}
+ else
+ relocation_skip (reloc, read_ctx_get_offset (ctx),
+ &where, skip_mismatched);
}
/* Relocate the value if appropriate. */
}
UNREACHABLE;
}
+
+bool
+read_generic_value (read_ctx *ctx,
+ form_width_t width, storage_class_t storclass,
+ where const *where, uint64_t *valuep, read_ctx *blockp)
+{
+ uint64_t value;
+ if (storclass == sc_value
+ || storclass == sc_block)
+ {
+ if (!read_sc_value (&value, width, ctx, where))
+ return false;
+ if (valuep != NULL)
+ *valuep = value;
+ if (storclass == sc_value)
+ return true;
+ }
+
+ unsigned char const *start = ctx->ptr;
+ if (storclass == sc_string)
+ {
+ if (!read_ctx_read_str (ctx))
+ return false;
+ }
+ else if (storclass == sc_block)
+ {
+ if (!read_ctx_skip (ctx, value))
+ return false;
+ }
+
+ if (blockp != NULL)
+ {
+ if (!read_ctx_init_sub (blockp, ctx, start, ctx->ptr))
+ return false;
+ }
+
+ return true;
+}
bool read_sc_value (uint64_t *valuep, form_width_t width,
read_ctx *ctx, where const *where);
+/// Read value depending on the form width and storage class.
+/// Value is returned via VALUEP, if that is non-NULL; for block
+/// forms, the value is block length. Block context is returned via
+/// BLOCKP, in non-NULL; for string class, the block is the string
+/// itself.
+bool read_generic_value (read_ctx *ctx,
+ form_width_t width, storage_class_t storclass,
+ where const *where, uint64_t *valuep,
+ read_ctx *blockp);
+
#endif//DWARFLINT_CHECKED_READ_HH