Device-Tree Alias·Label Debugging — What to Check and How to Align

Logs mention serial0 while the DTS only shows a uart0: label; an overlay target = <&i2c1> works, yet /aliases still points i2c1 at an old SoC path. That kind of name mix-up usually means treating alias · label · node as the same thing.

This post has three axes only: what is an alias? · label vs node? · debug tips? Overlay -@ / __symbols__ belongs with device-tree-overlay-debug; here the focus is aligning public aliases and source labels. No board MB measurements, prices, invented field stories, or affiliates.

Grounded in the Device Tree Specification — /aliases, DTS Labels, and the Linux DeviceTree Kernel API (of_find_node_opts_by_path, of_alias_get_id, and related helpers).

What is an alias?

One-line answer: An alias is a property on the root /aliases node: name = short public nickname, value = that node’s full path string. It is not the same as a DTS label such as uart0:.

Spec summary (§3.3 /aliases):

ItemRule
LocationDirect child of root, node name /aliases
Property nameThe alias name (public short name)
Property valueFull path string (need not be a leaf)
Name charsetLowercase a-z, digits 0-9, - only · 1–31 chars
ClientsWhen treating a string as a device path, detect and use aliases

Spec example (paths are illustrative, not a claim about a specific board):

aliases {
    serial0 = "/simple-bus@fe000000/serial@llc500";
    ethernet0 = "/simple-bus@fe000000/ethernet@31c000";
};

In DTS it is also common to fill the path via a label. Outside a cell array, &Label expands to that node’s full path (§6.3):

aliases {
    serial0 = &uart0;   /* → full path string of the uart0-labeled node */
};

On the Linux OF side (Kernel API):

  • of_find_node_opts_by_path(path, …) — if path does not start with /, it is treated as a property name under /aliases.
  • of_alias_get_id(np, stem) / of_alias_get_highest_id(stem) — obtain the index from stem+number aliases such as serial0, serial1.
  • /chosen properties like stdout-path may be an alias per the Spec (§3.5).

Do not: assume the kernel “knows” a DTS label name (uart0) as an alias. Without an /aliases entry, path lookup will not resolve that name.

Label vs node?

One-line answer: A node is the real tree object (name, unit-address, properties). A label is a DTS-only identifier. Labels are not encoded into the DTB (Spec §6.2).

Aspectnodelabelalias
WhereTree (DTS→DTB)DTS only/aliases property (path string in DTB)
Syntaxserial@llc500 { … }uart0: serial@…serial0 = "/…/serial@…";
Referencesfull path / phandle&uart0short path name serial0
In DTBEncoded as node/propertiesNot encodedEncoded as path-string property
Length/charsetNode-name rules1–31 · 0-9a-zA-Z_ · must not start with a digit1–31 · a-z0-9- only (lowercase)

How & expands (§6.3):

  1. Inside a cell array < &label > → that node’s phandle (number). Example: interrupt-parent = <&mpic>;
  2. Outside a cell array prop = &label; → that node’s full path string. Example: ethernet0 = &EMAC0;
  3. Path form: <&{/soc/interrupt-controller@40000}>

Node shape:

[label:] node-name[@unit-address] {
    [properties]
    [child nodes]
};

A phandle is a unique numeric ID for a node within the tree; most DTS files omit explicit phandle properties and dtc inserts them when building the DTB (basics · phandle). Labels exist so humans can write &refs in source; aliases exist so boot/firmware/drivers can speak short public names that resolve to paths at runtime.

Confusion points:

  • The same node may carry a uart0: label and a serial0 alias. The names need not match.
  • Overlay target = <&i2c1> is about base labels/symbols; /aliases i2c1 = "/…" is a separate entry. Fixing only one side leaves the other wrong.
  • With dtc -@, __symbols__ may map label→path. That is a symbol table for overlays, not the Spec /aliases node.

Debug tips?

One-line answer: Align in order: (1) /aliases path strings → (2) real node exists → (3) DTS labels/& refs → (4) kernel stem ids. Drop the assumption that “label name = alias name.”

1) Start with aliases on the live tree

# Runtime (when permitted) — alias properties = path strings
ls /proc/device-tree/aliases/
cat /proc/device-tree/aliases/serial0   # may be NUL-terminated

# Or dump FS form as DTS
dtc -I fs -O dts /proc/device-tree 2>/dev/null | sed -n '/aliases/,/^};/p'

Check: alias spelling, whether the value is the current full path, and whether a merge/overlay moved the node while the string stayed stale.

2) Labels exist only in source

# Binary → source: labels (: name) were never in the DTB — missing labels in a dump is normal
dtc -I dtb -O dts -o dumped.dts your.dtb

# Symbolized builds may show label→path under __symbols__ (overlay use)
grep -n '__symbols__\|aliases' dumped.dts

Symptom map:

SymptomSuspect
of_find_node_by_path("uart0") failsuart0 is not an alias. Add /aliases or use a full path / & rules
serial0 resolves but wrong UART/aliases path string is stale (node moved/address changed)
Overlay target = <&foo> failsBase label/symbol issue (-@, __symbols__) — separate from aliases
ttyS index unexpectedCheck serialN stem N (of_alias_get_id) and binding practice
DTS has foo: but dumped DTB does notExpected — labels are not encoded in the DTB

3) One checklist for label ↔ alias

[ ] Label name (DTS):     uart0
[ ] Node path:            /soc/serial@...
[ ] Alias property name:  serial0
[ ] Alias value string:   matches Node path after merge
[ ] Cell refs use:        <&uart0>  (phandle)
[ ] Path-style refs use:  &uart0 or "/soc/serial@..." outside <>
[ ] chosen/stdout-path:   full path OR alias name per Spec

Copy-paste order:

1. Locate /aliases in merged DTS or live tree.
2. For each public name (serial0, ethernet0, …): read path string.
3. Resolve that path — node must exist with expected compatible/status.
4. Grep DTS for "label:" used by &refs and overlays — separate from step 2.
5. If stem IDs matter, list aliases matching ^stem[0-9]+$ and sort by N.
6. Never invent board-specific timings/prices; fix names and paths only.

4) Pin expected behavior with kernel APIs

  • Path/alias resolution: of_find_node_opts_by_path
  • Stem index: of_alias_get_id / of_alias_get_highest_id
  • Phandle resolution: of_find_node_by_phandle, of_parse_phandle*

If a driver or boot doc says “needs serial0 alias,” the contract is an /aliases property with that name — a DTS label uart0: alone is not enough.

One-line wrap-up: label = source & handle, alias = /aliases path shortcut, node = tree object. Debug path strings and node presence first; treat labels as the compile/overlay reference axis.

FAQ

Must alias and label names match?

No. Common practice keeps a numbered public alias (serial0) and a block label (uart0:). If you make them match, do it deliberately and document it in a table.

If /aliases uses &label, what remains in the DTB?

It is an out-of-cell reference, so dtc expands it to a full path string. Runtime keeps that string, not the label token.

May stdout-path be an alias?

Yes. Per the Spec, /chosen stdout-path / stdin-path values may be aliases. Clients must resolve aliases when treating the value as a path.

Why do label and alias character sets differ?

Different Spec rules. Labels allow A-Z and _ and must not start with a digit; aliases are lowercase, digits, and - only. Copying an uppercase label into an alias name yields an invalid alias name.

Sources