Browse Source

Fix missing labels when emitting dts format

When there is a label inside a sequence of ints at the end of a
property, an assertion is hit because write_propval() expects all the
labels to be at the very end of the property data. This is clearly wrong
behaviour.

To reproduce run: "dtc -O dts tests/label01.dts". dtc fails on property
/randomnode/blob.

Fix by reworking the write_propval() loop to remove the separate
iterating over label markers. Instead handle the label markers as part
of the main marker iteration loop. This guarantees that each label
marker is handled at the right location, even if all the data markers
have already been handled, and has the added advantage of making the
code simpler.

However, a side effect of this code is that a label at the very end of
an int sequence will be emitted outside the sequence delimiters. For
example:

	Input:  intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
	Output: intprop = < 1 2 >, L1: L2: < 3 4 > L3: L4:;

The two representations are equivalent in the data model, but the
current test case was looking for the former, but needed to be modified
to look for the later. The alternative would be to render labels before
closing the sequence, but that makes less sense syntactically because
labels between sequences are normally to point at the next one, not the
former. For example:

	Input:  intprop = < 1 2 L1: >, L2: < 3 4 L3: > L4:;
	Output: intprop = < 1 2 L1: L2: >,  < 3 4 L3: L4: >;

DTC doesn't current have the information to know if the label should be
inside or outside the sequence, but in common usage, it is more likely
that L1 & L2 refer to the second sequence, not the end of the first.

Fixes: 32b9c61307 ("Preserve datatype markers when emitting dts
format")

Reported-by: Łukasz Dobrowolski <lukasz.dobrowolski@nokia.com>
Signed-off-by: Grant Likely <grant.likely@arm.com>
Cc: David Gibson <david@gibson.dropbear.id.au>
Cc: Rob Herring <robh@kernel.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
main
Grant Likely 6 years ago committed by David Gibson
parent
commit
8c59a97ce0
  1. 4
      tests/type-preservation.dts
  2. 45
      treesource.c

4
tests/type-preservation.dts

@ -9,12 +9,12 @@ @@ -9,12 +9,12 @@
reg = <0x01>;
int-array = <0x00 0x01>, int_value_label: <0x02 0x03>;
int8 = [56];
int8-array = [00 12 34 56 label:];
int8-array = [00 12 34 56] label:;
int16 = /bits/ 16 <0x3210>;
int16-array = /bits/ 16 <0x1234 0x5678 0x90ab 0xcdef>;
int16-matrix = /bits/ 16 <0x1234 0x5678>, <0x90ab 0xcdef>;
int64 = /bits/ 64 <0x200000000>;
int64-array = /bits/ 64 <0x100000000 0x00 int64_array_label_end:>;
int64-array = /bits/ 64 <0x100000000 0x00> int64_array_label_end:;
a-string-with-nulls = "foo\0bar", "baz";

subsub1: subsubnode {

45
treesource.c

@ -216,7 +216,7 @@ static void write_propval(FILE *f, struct property *prop) @@ -216,7 +216,7 @@ static void write_propval(FILE *f, struct property *prop)
return;
}

fprintf(f, " = ");
fprintf(f, " =");

if (!next_type_marker(m)) {
/* data type information missing, need to guess */
@ -227,32 +227,23 @@ static void write_propval(FILE *f, struct property *prop) @@ -227,32 +227,23 @@ static void write_propval(FILE *f, struct property *prop)
m = &dummy_marker;
}

struct marker *m_label = prop->val.markers;
for_each_marker(m) {
size_t chunk_len;
size_t chunk_len = (m->next ? m->next->offset : len) - m->offset;
size_t data_len = type_marker_length(m) ? : len - m->offset;
const char *p = &prop->val.val[m->offset];

if (!has_data_type_information(m))
continue;

chunk_len = type_marker_length(m);
if (!chunk_len)
chunk_len = len - m->offset;

if (emit_type != TYPE_NONE)
fprintf(f, "%s, ", delim_end[emit_type]);
emit_type = m->type;

for_each_marker_of_type(m_label, LABEL) {
if (m_label->offset > m->offset)
break;
fprintf(f, "%s: ", m_label->ref);
if (has_data_type_information(m)) {
emit_type = m->type;
fprintf(f, " %s", delim_start[emit_type]);
}

fprintf(f, "%s", delim_start[emit_type]);
if (m->type == LABEL)
fprintf(f, " %s:", m->ref);

if (chunk_len <= 0)
if (emit_type == TYPE_NONE) {
assert(chunk_len == 0);
continue;
}

switch(emit_type) {
case TYPE_UINT16:
@ -270,15 +261,15 @@ static void write_propval(FILE *f, struct property *prop) @@ -270,15 +261,15 @@ static void write_propval(FILE *f, struct property *prop)
default:
write_propval_int(f, p, chunk_len, 1);
}
}

/* Wrap up any labels at the end of the value */
for_each_marker_of_type(m_label, LABEL) {
assert (m_label->offset == len);
fprintf(f, " %s:", m_label->ref);
if (chunk_len == data_len) {
size_t pos = m->offset + chunk_len;
fprintf(f, pos == len ? "%s" : "%s,",
delim_end[emit_type] ? : "");
emit_type = TYPE_NONE;
}
}

fprintf(f, "%s;\n", delim_end[emit_type] ? : "");
fprintf(f, ";\n");
}

static void write_tree_source_node(FILE *f, struct node *tree, int level)

Loading…
Cancel
Save