How can Chrome get its own build ID on Chrome OS?

169 views
Skip to first unread message

Simon Que

unread,
Jun 28, 2016, 12:21:07 AM6/28/16
to Chromium-dev
I'm trying to obtain the Chrome binary build ID from within Chrome source code on Chrome OS. How can this be done?

Simon

Mike Frysinger

unread,
Jun 28, 2016, 12:48:35 AM6/28/16
to Simon Que, Chromium-dev
do you mean "build id" as in:
$ file /opt/google/chrome/chrome
..., BuildID[sha1]=f52b2efc951dbd6f7111112b8bb019615ce81ace, ...

that will be included in the program headers at runtime.  you can probably use dl_iterate_phdr() to locate the loaded PT_NOTE, then walk the notes to find NT_GNU_BUILD_ID, and then that'll contain that field.
-mike

On Tue, Jun 28, 2016 at 12:19 AM, Simon Que <sq...@chromium.org> wrote:
I'm trying to obtain the Chrome binary build ID from within Chrome source code on Chrome OS. How can this be done?

Simon

--
--
Chromium Developers mailing list: chromi...@chromium.org
View archives, change email options, or unsubscribe:
http://groups.google.com/a/chromium.org/group/chromium-dev

Simon Que

unread,
Jun 28, 2016, 2:06:42 AM6/28/16
to Mike Frysinger, Chromium-dev
I see this file under src/breakpad that has what seems to be a build ID reading feature:

Is code under src/breakpad includable from src/components?

Mike Frysinger

unread,
Jun 28, 2016, 2:20:57 AM6/28/16
to Simon Que, Chromium-dev
i don't think you want to do that.  that operates on files-on-disk, not images-in-memory.
-mike

Primiano Tucci

unread,
Jun 28, 2016, 5:34:52 AM6/28/16
to vap...@chromium.org, Simon Que, Chromium-dev
Can you specify what you mean with "Build ID"?
Do you mean something like  51.0.2704.103 (version) ?
Or something like aa7c8d23c098e96a388ffedf6698230bda650bb3-refs/branch-heads/2704@{#723} (revision)? 
Or something like 986ACBCE115D39FBBC045F2C1D413A430 (Breakpad Module GUID) ?
Or something like the NT_GNU_BUILD_ID Mike pointed out?

If the latter I don't think there is any code ouside of breakpad that read the .note.gnu.build-id. What do you need to achieve?

Simon Que

unread,
Jun 28, 2016, 6:54:30 AM6/28/16
to Primiano Tucci, Mike Frysinger, Chromium-dev
The one that shows up in "readelf -n":

Displaying notes found at file offset 0x000001d0 with length 0x00000024:
  Owner                 Data size Description
  GNU                  0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: b4f41d35a6bf2f717506a4e2e00f9ff7ff8fe5e2

Simon Que

unread,
Jun 28, 2016, 8:41:59 AM6/28/16
to Mike Frysinger, Chromium-dev, Primiano Tucci
Looking at src/native_client/src/untrusted/minidump_generator/build_id.cc, I see that the walking of the notes requires accessing memory at the following symbol:

 extern const char __ehdr_start __attribute__((weak));

Is this supported on Chrome OS? Is this the most straightforward way to do it?


On Tue, Jun 28, 2016 at 1:47 PM, Mike Frysinger <vap...@chromium.org> wrote:

Primiano Tucci

unread,
Jun 28, 2016, 11:27:07 AM6/28/16
to Simon Que, Mike Frysinger, Chromium-dev
I am not sure you can rely on the fact that the program headers are mapped in the address space and, more importantly, that you know the offset of note_gnu_build_id. That code you point out is NACL code that can make stronger assumptions on the toolchain and loader. Essentially you'd need to parse the elf file and its headers from within chrome to get it.

My question still holds: what are you trying to achieve here? Maybe there is a way to achieve the same without requiring the note.gnu.build-id at all?

Simon Que

unread,
Jun 28, 2016, 11:51:35 AM6/28/16
to Primiano Tucci, Mike Frysinger, Chromium-dev
I'm trying to find a way to connect memory leak reports with Chrome build IDs so that the call stacks in the leak reports could be symbolized via build ID lookup, which is currently the case with metrics::PerfProvider-collected data.

Please see the conversation in the comments in this doc (Google internal only):


Alexei Svitkine

unread,
Jun 28, 2016, 11:54:36 AM6/28/16
to Simon Que, Primiano Tucci, Mike Frysinger, Chromium-dev
Shouldn't you be able to symbolize based on Chrome's version number, which should be more readily available?

Mike Frysinger

unread,
Jun 28, 2016, 11:58:51 AM6/28/16
to Simon Que, Chromium-dev, Primiano Tucci
__ehdr_start is an automatic symbol provided by the linker (bfd & gold).  you can rely on that working under Linux.  whether you should is a different question ... imo you should still be using dl_iterate_phdr as that's what it was designed for.
-mike

Mike Frysinger

unread,
Jun 28, 2016, 12:04:03 PM6/28/16
to Primiano Tucci, Simon Que, Chromium-dev
yes, you can rely on the phdrs always being mapped.  by definition, it's the thing in ELF files that tell the system what & how to actually load the ELF into memory.  plus, the phdrs list themselves :).

you don't need to know the offset of note_gnu_build_id.  simply walk the phdrs list until you find PT_NULL and then stop.  if you see a PT_NOTE in between, you check its type using the well known structure ElfW(Nhdr).n_type.  if it's NT_GNU_BUILD_ID, then you've found the build id.

but i agree with your question -- getting background as to what you're trying to do would be helpful.
-mike

Mike Frysinger

unread,
Jun 28, 2016, 12:07:55 PM6/28/16
to Alexei Svitkine, Simon Que, Primiano Tucci, Chromium-dev
Chrome OS might have the same Chrome version number across diff builds.  if the OS updates, we do a new CrOS build (and get a new CrOS version), but the Chrome source/version doesn't change.

theoretically, buildid shouldn't change either, but not sure how deterministic the Chrome buidls are in CrOS currently.
-mike

Primiano Tucci

unread,
Jun 29, 2016, 3:29:16 AM6/29/16
to Mike Frysinger, Alexei Svitkine, Simon Que, Chromium-dev
I don't have any CrOS knowledge but I imagine that at some level you have one form of "version" which deterministically points at a given chrome build and system build ? Having to do all sort of ELF headers traversal in chrome just for the sake of knowing which are the right symbols to use seems a bit overkill.

yes, you can rely on the phdrs always being mapped
not if you don't have a PHDR section in the elf which tells the loader to keep them mapped.

>   by definition, it's the thing in ELF files that tell the system what & how to actually load the ELF into memory
Right, but nothing requires them to be mapped by definition. The loader have to guarantee to map the sections specified in the elf at the vaddr provided. If nothing loads the PHDR the loader can just throw them away after the loading is done.

Anyways, this seems really overkill to lookup the version of the binary. 
 

Victor Khimenko

unread,
Jun 29, 2016, 6:06:15 AM6/29/16
to Primiano Tucci, Mike Frysinger, Alexei Svitkine, Simon Que, Chromium-dev
On Wed, Jun 29, 2016 at 9:28 AM, Primiano Tucci <prim...@chromium.org> wrote:
I don't have any CrOS knowledge but I imagine that at some level you have one form of "version" which deterministically points at a given chrome build and system build ? Having to do all sort of ELF headers traversal in chrome just for the sake of knowing which are the right symbols to use seems a bit overkill.

Uhm. That ELF header is there specifically to make it possible to find the right symbolds. Why invent some roundabout ways to do that if reliable and [relatively] simple method is available?
 
yes, you can rely on the phdrs always being mapped
not if you don't have a PHDR section in the elf which tells the loader to keep them mapped.

Maybe in some other libc (on macOS or Android). But glibc includes function which traverses headers of loaded libraries thus you could just use it:

It's public API and as such would be supported even if glibc will decide to not mmap headers.
 
>   by definition, it's the thing in ELF files that tell the system what & how to actually load the ELF into memory
Right, but nothing requires them to be mapped by definition. The loader have to guarantee to map the sections specified in the elf at the vaddr provided. If nothing loads the PHDR the loader can just throw them away after the loading is done.

Anyways, this seems really overkill to lookup the version of the binary.  
 
Why? It's just a simple call to dl_iterate_phdrr with trival callback AFAICS...

Primiano Tucci

unread,
Jun 29, 2016, 7:33:53 AM6/29/16
to Victor Khimenko, Mike Frysinger, Alexei Svitkine, Simon Que, Chromium-dev
On Wed, Jun 29, 2016 at 12:05 PM, Victor Khimenko <kh...@chromium.org> wrote:
Why invent some roundabout ways to do that if reliable and [relatively] simple method is available?
it's not about inventing roundabouts, The question here is the other way round: why the existing code is not sufficient?
I thought that mapping a Chrome or OS version to symbols was a solved problem and I was wondering if we could do that in this context without adding new code. 

Why? It's just a simple call to dl_iterate_phdrr with trival callback AFAICS.
To get the program header, right. Then you need to find the ".note.gnu.build-id" section inside there.  
I am not saying it's impossible, as Simon pointed out, there is code in NaCl that does that already. 
But that doesn't look as simple as just printing a string (which is what version_info does).
Hence my original question: why cannot we just use one of the existing versions/revisions? 
Maybe the answer is that we can't and we really need this, but would be nice to make sure that it is the case before introducing and exposing yet another GetVersion/BuildID/Revision() method.

Victor Khimenko

unread,
Jun 29, 2016, 8:18:48 AM6/29/16
to Primiano Tucci, Mike Frysinger, Alexei Svitkine, Simon Que, Chromium-dev
On Wed, Jun 29, 2016 at 1:33 PM, Primiano Tucci <prim...@chromium.org> wrote:
On Wed, Jun 29, 2016 at 12:05 PM, Victor Khimenko <kh...@chromium.org> wrote:
Why invent some roundabout ways to do that if reliable and [relatively] simple method is available?
it's not about inventing roundabouts, The question here is the other way round: why the existing code is not sufficient?

Because it does not use ".note.gnu.build-id" ?
 
I thought that mapping a Chrome or OS version to symbols was a solved problem

Indeed. You can easily match Chrome or OS version to bazillion symbol sets (different compilers, different configurations setting, etc). Next step?

and I was wondering if we could do that in this context without adding new code. 

See above. A single set of sources could produce many, many, different sets of debug symbols. And ".note.gnu.build-id" is mechanism which exist specifically to resolve that ambiguity:
 
Why? It's just a simple call to dl_iterate_phdrr with trival callback AFAICS.
To get the program header, right. Then you need to find the ".note.gnu.build-id" section inside there.  
I am not saying it's impossible, as Simon pointed out, there is code in NaCl that does that already. 
But that doesn't look as simple as just printing a string (which is what version_info does).
Hence my original question: why cannot we just use one of the existing versions/revisions? 
Maybe the answer is that we can't and we really need this, but would be nice to make sure that it is the case before introducing and exposing yet another GetVersion/BuildID/Revision() method.

It's not impossible. But as I've said all other methods are roundabout ones: they rely on the reproducible builds and on the fact that we catch regressions there if/when they occur because they use INPUTS of the build process. ".note.gnu.build-id" uses OUTPUT of the build process and thus it's significantly more robust - but the price is that exact need to parse binaries produced as the result of a build process: since BuildId does not exist before binary is actually built there are no easy and convenient way to print it.

Mike Frysinger

unread,
Jun 29, 2016, 10:03:31 AM6/29/16
to Victor Khimenko, Primiano Tucci, Alexei Svitkine, Simon Que, Chromium-dev
if you take the tuple of (CrOS version, $BOARD), it will be unique and map back to a specific known build.  however, getting the Chrome symbol id or buildid out of that is not trivial as we don't throw that info into a db anywhere (afaik).  you should be able to construct a GS URI pretty easily from the version/board, but then you'd have to fetch some large tarballs in order to extract either bit of data.
-mike
Reply all
Reply to author
Forward
0 new messages