[CMake] Fwd: Save stripped debugging information

Michael Hertling mhertling at online.de
Thu Oct 13 14:09:04 EDT 2011


On 10/12/2011 03:40 PM, Rolf Eike Beer wrote:
>> On 10/03/2011 09:18 AM, Yuri Timenkov wrote:
>>> Hi Michael,
>>>
>>> On Sun, Oct 2, 2011 at 6:07 PM, Michael Hertling
>>> <mhertling at online.de>wrote:
>>>
>>>> On 10/01/2011 10:07 AM, Yuri Timenkov wrote:
>>>>> that's the problem: you don't know neither file name nor it's
>>>>> location,
>>>>> especially in multi-configuration generators.
>>>>
>>>> You *do* know a debug file's name and location, either because you must
>>>> generate it explicitly (objcopy approach) or via the concerned target's
>>>> $<TARGET_FILE_DIR:...> generator expression in custom targets/commands
>>>> (Visual approach). Otherwise, a debug file with unknown name and/or
>>>> location would be rather useless.
>>>>
>>> I'm sorry that you misunderstood me, but I was concerned about install()
>>> commands.
>>>
>>> CMake already does a lot of things to make different platforms and
>>> generators work in same way. As it was noted before, install already
>>> knows
>>> about such subtleties between generators and platforms like export
>>> libraries. So why not make it aware of separate debug information?
>>
>> Because, IMO, the platform/generator independent extraction and/or
>> recognition of debug info files is significantly more difficult to
>> specify than the handling of DLLs along with their import libraries
>> in VS, e.g. AFAICS, the latter works well since the import libraries
>> are generated next to their DLLs sharing the same base name, and both
>> are covered by INSTALL()'s RUNTIME/ARCHIVE DESTINATION clauses which
>> also have a defined meaning on *nix. For VS alone, the installation
>> of debug info files would in fact be as easy as the installation of
>> an import library, but how would you specify and parameterize this
>> task on *nix? With the GNU toolchain, CMake can't know in advance if
>> and how debug info files are generated, where they're written to etc.
> 
> I think you got something reverse here.
> 
> To actually get the debug information in a separate file with binutils you
> need to run objcopy. [...]

No, you can use the full symbol-equipped executable as debug info file:

<cite src="man objcopy">

Also the --only-keep-debug step is optional. You could instead do this:

   1. Link the executable as normal.
   2. Copy foo to foo.full
   3. Run objcopy --strip-debug foo
   4. Run objcopy --add-gnu-debuglink=foo.full foo

i.e., the file pointed to by the --add-gnu-debuglink can be the full
executable. It does not have to be a file created by the
--only-keep-debug switch.

</cite>

As you can see, the debug info file is *not* generated by objcopy; it's
just a copy of the original non-stripped binary. The --only-keep-debug
switch is virtually the complement of --strip-debug; essentially, it
removes non-debug-related sections - convenient but not necessary.

> [...] You _specify_ to objcopy where to put the debug file.
> So CMake would need to specify this, i.e. can always know where these
> files end up.
> 
> The build-id thing is optional, [...]

It's as optional as the usage of objcopy.

> [...] and as far as I understand this the
> primary use case is to find the debug symbols corresponding to an
> executable. [...]

Right.

> [...] The usual thing with gnu-debug-link is still done on those
> binaries, so the build-id thing is on top of that. [...]

No, that's not true. Look at the following CMakeLists.txt:

CMAKE_MINIMUM_REQUIRED(VERSION 2.8 FATAL_ERROR)
PROJECT(BUILDID C)
SET(CMAKE_VERBOSE_MAKEFILE ON)
SET(BUILDID "abcdef1234")
STRING(SUBSTRING "${BUILDID}" 0 2 BUILDIDPREFIX)
STRING(SUBSTRING "${BUILDID}" 2 8 BUILDIDSUFFIX)
FILE(WRITE ${CMAKE_BINARY_DIR}/main.c "int main(void){return 0;}\n")
ADD_EXECUTABLE(main main.c)
SET_TARGET_PROPERTIES(main PROPERTIES
    LINK_FLAGS "-Wl,--build-id=0x${BUILDID}")
ADD_CUSTOM_COMMAND(TARGET main POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy $<TARGET_FILE:main>
                                     ${CMAKE_BINARY_DIR}/main.debug
    COMMAND ${CMAKE_STRIP} -g $<TARGET_FILE:main>)
INSTALL(FILES ${CMAKE_BINARY_DIR}/main.debug
    DESTINATION ${CMAKE_BINARY_DIR}/.build-id/${BUILDIDPREFIX}
    RENAME ${BUILDIDSUFFIX}.debug)

Configure with CMAKE_BUILD_TYPE==debug and build; subsequently, invoke

gdb -ex "set debug-file-directory ." -ex "file main"

from within CMAKE_BINARY_DIR, and you will read "no debugging symbols
found" as expected. Now, issue "make install", re-invoke gdb and read:

"Reading symbols from .../.build-id/ab/cdef1234.debug"

As you can see, the debug info file is connected with the stripped
executable *solely* by the build ID; no objcopy in sight. In fact, the
build-ID method and the debug-link method are totally independent from
each other and can be used alternatively or jointly to connect a debug
info file with its executable; gdb does even check the build ID first.

> [...] This would only affect
> the install stage at all, i.e. if CMake would install these debug symbols
> in the global debug directory.
> 
> So, to make things short:
> 
> -call objcopy with target filename and the output filename -> both come
> from CMake, no magic

As I have already outlined, objcopy is not necessary to generate or
process debug info files, and it is no POSIX standard. Debug info files
might be generated solely by the linker (VS), solely by a supplementary
tool (objcopy --only-keep-debug/--add-gnu-debuglink) or both (build ID
with objcopy --only-keep-debug), and there might be parameters the user
needs or wants to specify (build ID string). If all this is to work in
a platform/generator-independent manner without seriously limiting the
user's choices: Much magic, IMO.

> -optionally, and only on installation, check if the file has a build-id
> (using readelf, objdump or whatever) [...]

objdump -s -j .note.gnu.build-id <binary>

BTW, this would make INSTALL() depend on objdump or another tool.

> [...] and place a link from
> /usr/lib/debug/.build-id (or whereever) to the debug file

The fact that a binary contains a build ID does not necessarily mean
that it is or has a debug info file; a build ID can also serve other
identificatory purposes. So, this check will probably turn out to be
insufficient since these cases can't be distinguished automatically.

> So AFAICT there is no magic knowledge or searching for something involved
> at all.
> 
> Or am I getting something seriously wrong here?

To my mind, the discussion is not about debug-link vs. build-ID or
objcopy vs. not-objcopy; these are just examples for the diversity
of the debug info files' generation and processing. Instead, the
discussion is actually about:

(1) Should CMake be taught to generate debug info files by itself?
    While this is trivial with VS, it is - IMO - hardly feasible on
    *nix in a manner that does not restrict the user's possibilities.

(2) Should CMake just install debug info files, the latters generated
    before by the project? While this would probably be quite easy to
    implement for VS, it is - IMO - hardly feasible on *nix without
    (1) as CMake can't know the files' names and locations a priori.
    Of course, one might agree on a convention that the debug info
    file of a target xyz is to be named xyz.debug and placed next
    to xyz.

(3) If one comes up with a solution for (2), perhaps by the
    aforementioned convention, what is the value added by

    INSTALL(TARGETS ... DEBUG DESTINATION ...)

    or

    INSTALL(TARGETS ... DEBUG_SYMBOLS ...)

    as this can already be accomplished with INSTALL(FILES ...)?
    Just skidding over the platform-dependent filename extensions?

As I recently replied to Yuri, I am not opposed to (1) or (2), but
forcing me to use objcopy --only-keep-debug/--add-gnu-debuglink to
generate debug info files would - to my taste - not be acceptable.

However, a possible approach to this topic I could imagine is the
following: Add a new target property DEBUG_INFO_FILES[_<CONFIG>],
perhaps initialized with $<TARGET_FILE_DIR:target>.pdb in VS and
$<TARGET_FILE_DIR:target>.debug on *nix. If this property is set,
this means that the denoted debug info files are to be generated,
and INSTALL(TARGETS target DEBUG DESTINATION ...) would know where
to find them. Regarding the Makefile generators, we would probably
need an additional rule variable CMAKE_<LANG>_GENERATE_DEBUG_INFO
or the like, but this would not account for an early role of the
linker with potential user-supplied parameters. If you have any
suggestions how to conceptually realize it, I'd be interested.

Regards,

Michael


More information about the CMake mailing list