Semantic for handles

Handles have a numeric value with no real meaning. However, we can associate a lot of information to a handle. Some information is available using zx_object_get_info but, fidlcat is not currently able to use this system call with a process it monitors (Zircon will implement it in a not too far future).

Some information is easy to infer. For example, if a process calls zx_channel_create, both handles are channels.

However, we also need more information. For handles which are defined at the program startup, we have some extra information. For example:

  • fd:1

  • dir:/svc

  • directory-request:/

That means that, for a handle, we can have three attributes:

  • a type (fd, dir, proc-self, vdso-vmo, ...).

  • a file descriptor (a numerical value mostly used by the fd type).

  • a path (a string value used, for example, by the dir type).

For handles created during the process life, we can infer this information by analysing the FIDL method calls.

For example, with these two syscalls:

echo_client_cpp 2378655:2378657 zx_channel_create(options:uint32: 0)
  -> ZX_OK (out0:handle: 712aee63, out1:handle: 3bdaedc3)

echo_client_cpp 2378655:2378657 zx_channel_write(
    handle:handle: 537aead7(dir:/svc), options:uint32: 0)
  sent request = {
    flags: uint32 = 3
    mode: uint32 = 493
    path: string = "fuchsia.sys.Launcher"
    object: handle = 712aee63
  -> ZX_OK

We know that handle 537aead7 is directory “/svc” (we get this information for the program startup).

Doing an open of “fuchsia.sys.Launcher” on this handle will open “/svc/fuchsia.sys.Launcher”.

That means that the handle 712aee63 in a remote process will refer to “/svc/fuchsia.sys.Launcher”.

Because 712aee63 and 3bdaedc3 are linked (they have been created by the same zx_channel_create), we can now know that, everytime we use 3bdaedc3, it refers to dir:/svc/fuchsia.sys.Launcher

Each time fidlcat has to print handle 3bdaedc3, it can add the infered information:


This is way more readable.

How to infer handle semantic

To be able to infer this kind of information, we need to understand the semantic of FIDL messages which use handles.

Because this is currently specific to fidlcat, we decided not to put this information in the FIDL files. Instead, we have a file embeded within fidlcat which describes the semantic for the sdk messages.

For example, for the Directory Open method, we can define:

library {
  Directory::Open {
    request.object = handle / request.path;

This says that, everytime we have an Open method, the semantic for the field object (a handle) which is found within the request, is equal to the semantic of the handle used by the zx_channel_write syscall concatenated with the value of the field path.

With this simple rule, we are now able to infer the information about any handle used within an Open.

Description of the grammar for the semantic files.

File ::= LibraryDefinition*

LibraryDefinition ::= ‘library’ LibraryName ‘{’ MethodDefinition* ‘}

LibraryName ::= IdentifierWithDots

MethodDefinition ::= ProtocolName ‘::’ MethodName ‘{’ Assignment* ‘}

ProtocolName ::= Identifier

MethodName ::= Identifier

Assignment ::= Expression ‘=’ Expression ‘;

Expression ::= MultiplicativeExpression

MultiplicativeExpression ::= AccessExpression [ ‘/’ AccessExpression ]

AccessExpression ::= TerminalExpression ( ‘.’ FieldName )*

TerminalExpression ::= ‘request’ | ‘handle’ | HandleDescription | String

HandleDescription ::= ‘HandleDescription’ ‘(’ HandleType ‘,’ HandlePath ‘)

HandleType ::= Expression

HandlePath ::= Expression

FieldName ::= Identifier

Identifier: a sequence of letters, numbers and underscores which starts with a letter or an underscore.

IdentifierWithDots: a sequence of letters, numbers, dots and underscores which starts with a letter or an underscore.

String: a sequence of characters between single quotes. Single quotes and backslahes within a string must be escaped with a backslash.

Whitespaces (spaces, new lines, tabulations) are ignored (but they separate lexical items).

Semantic of expressions

Terminal expressions:

  • handle: the handle used to call zx_channel_write (or another system call which read/write FIDL messages).

  • request: the FIDL method given to the zx_channel_write.

  • HandleDescription: creates a handle description using the arguments. Both arguments must be strings.

The dot operator access a field within an object. It can be used on the terminal expression request. It can be also used on any expression with returns an object.

The slash operator concatenates a handle with a string. The result is a handle with the same type, with the same file descriptor value and with a path which is the contatanation of the handle path and the left string. The left of the operator must be a handle. The right of the operator must be a string.

It optimizes the result to have a canonical path.

For example, with “dir:/svc/.”, the canonical result is “dir:/svc”.

Assignments (with the “=” operator) assign the handle semantic on the right side to the handle on the left side. We don't modify the handle, we just modify its semantic.