diff options
| author | Ludovic Courtès <ludo@gnu.org> | 2018-08-21 22:39:41 +0200 |
|---|---|---|
| committer | Ludovic Courtès <ludo@gnu.org> | 2018-08-24 18:01:05 +0200 |
| commit | 93c333895a4e2dc9baabec8ade60d9d2ac0a91e2 (patch) | |
| tree | bcf3902e7435df4334792fa59e5039776ff4bba0 | |
| parent | e4297aa8b95cefa32e2595ce58886fc03b0561f7 (diff) | |
grafts: Add (guix build debug-link) and use it.
Fixes <https://bugs.gnu.org/19973>.
Reported by Mark H Weaver <mhw@netris.org>.
* guix/build/debug-link.scm: New file.
* guix/build/graft.scm (%graft-hooks): New variable.
(graft): Add #:hooks and honor it.
* guix/grafts.scm (graft-derivation/shallow): Add (guix build
debug-link) and (guix elf) to #:modules.
* tests/debug-link.scm: New file.
* Makefile.am (MODULES): Add guix/build/debug-link.scm.
(SCM_TESTS): Add tests/debug-link.scm.
| -rw-r--r-- | Makefile.am | 2 | ||||
| -rw-r--r-- | guix/build/debug-link.scm | 210 | ||||
| -rw-r--r-- | guix/build/graft.scm | 14 | ||||
| -rw-r--r-- | guix/grafts.scm | 4 | ||||
| -rw-r--r-- | tests/debug-link.scm | 158 |
5 files changed, 385 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index bdf1c63cee1..324674a60ee 100644 --- a/Makefile.am +++ b/Makefile.am | |||
| @@ -171,6 +171,7 @@ MODULES = \ | |||
| 171 | guix/build/svn.scm \ | 171 | guix/build/svn.scm \ |
| 172 | guix/build/syscalls.scm \ | 172 | guix/build/syscalls.scm \ |
| 173 | guix/build/gremlin.scm \ | 173 | guix/build/gremlin.scm \ |
| 174 | guix/build/debug-link.scm \ | ||
| 174 | guix/build/emacs-utils.scm \ | 175 | guix/build/emacs-utils.scm \ |
| 175 | guix/build/java-utils.scm \ | 176 | guix/build/java-utils.scm \ |
| 176 | guix/build/lisp-utils.scm \ | 177 | guix/build/lisp-utils.scm \ |
| @@ -363,6 +364,7 @@ SCM_TESTS = \ | |||
| 363 | tests/syscalls.scm \ | 364 | tests/syscalls.scm \ |
| 364 | tests/inferior.scm \ | 365 | tests/inferior.scm \ |
| 365 | tests/gremlin.scm \ | 366 | tests/gremlin.scm \ |
| 367 | tests/debug-link.scm \ | ||
| 366 | tests/bournish.scm \ | 368 | tests/bournish.scm \ |
| 367 | tests/lint.scm \ | 369 | tests/lint.scm \ |
| 368 | tests/publish.scm \ | 370 | tests/publish.scm \ |
diff --git a/guix/build/debug-link.scm b/guix/build/debug-link.scm new file mode 100644 index 00000000000..9167737fb3a --- /dev/null +++ b/guix/build/debug-link.scm | |||
| @@ -0,0 +1,210 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2018 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (guix build debug-link) | ||
| 20 | #:use-module (guix elf) | ||
| 21 | #:use-module ((guix build utils) | ||
| 22 | #:select (find-files elf-file? make-file-writable)) | ||
| 23 | #:use-module (rnrs bytevectors) | ||
| 24 | #:use-module (rnrs io ports) | ||
| 25 | #:use-module (srfi srfi-1) | ||
| 26 | #:use-module (system foreign) | ||
| 27 | #:use-module (ice-9 match) | ||
| 28 | #:export (debuglink-crc32 | ||
| 29 | elf-debuglink | ||
| 30 | set-debuglink-crc | ||
| 31 | |||
| 32 | graft-debug-links)) | ||
| 33 | |||
| 34 | ;;; Commentary: | ||
| 35 | ;;; | ||
| 36 | ;;; This module provides tools to deal with '.gnu_debuglink' sections in ELF | ||
| 37 | ;;; files. These sections are created by 'objcopy --add-gnu-debuglink' to | ||
| 38 | ;;; create separate debug files (info "(gdb) Separate Debug Files"). | ||
| 39 | ;;; | ||
| 40 | ;;; The main facility of this module is 'graft-debug-links', which allows us | ||
| 41 | ;;; to update the CRC that appears in '.gnu_debuglink' sections when grafting, | ||
| 42 | ;;; such that separate debug files remain usable after grafting. Failing to | ||
| 43 | ;;; do that, GDB would complain about CRC mismatch---see | ||
| 44 | ;;; <https://bugs.gnu.org/19973>. | ||
| 45 | ;;; | ||
| 46 | ;;; Code: | ||
| 47 | |||
| 48 | (define %crc32-table | ||
| 49 | ;; CRC table taken from "(gdb) Separate Debug Files". | ||
| 50 | ;; TODO: Wouldn't it be nice to generate it "from source" with a macro? | ||
| 51 | #(#x00000000 #x77073096 #xee0e612c #x990951ba #x076dc419 | ||
| 52 | #x706af48f #xe963a535 #x9e6495a3 #x0edb8832 #x79dcb8a4 | ||
| 53 | #xe0d5e91e #x97d2d988 #x09b64c2b #x7eb17cbd #xe7b82d07 | ||
| 54 | #x90bf1d91 #x1db71064 #x6ab020f2 #xf3b97148 #x84be41de | ||
| 55 | #x1adad47d #x6ddde4eb #xf4d4b551 #x83d385c7 #x136c9856 | ||
| 56 | #x646ba8c0 #xfd62f97a #x8a65c9ec #x14015c4f #x63066cd9 | ||
| 57 | #xfa0f3d63 #x8d080df5 #x3b6e20c8 #x4c69105e #xd56041e4 | ||
| 58 | #xa2677172 #x3c03e4d1 #x4b04d447 #xd20d85fd #xa50ab56b | ||
| 59 | #x35b5a8fa #x42b2986c #xdbbbc9d6 #xacbcf940 #x32d86ce3 | ||
| 60 | #x45df5c75 #xdcd60dcf #xabd13d59 #x26d930ac #x51de003a | ||
| 61 | #xc8d75180 #xbfd06116 #x21b4f4b5 #x56b3c423 #xcfba9599 | ||
| 62 | #xb8bda50f #x2802b89e #x5f058808 #xc60cd9b2 #xb10be924 | ||
| 63 | #x2f6f7c87 #x58684c11 #xc1611dab #xb6662d3d #x76dc4190 | ||
| 64 | #x01db7106 #x98d220bc #xefd5102a #x71b18589 #x06b6b51f | ||
| 65 | #x9fbfe4a5 #xe8b8d433 #x7807c9a2 #x0f00f934 #x9609a88e | ||
| 66 | #xe10e9818 #x7f6a0dbb #x086d3d2d #x91646c97 #xe6635c01 | ||
| 67 | #x6b6b51f4 #x1c6c6162 #x856530d8 #xf262004e #x6c0695ed | ||
| 68 | #x1b01a57b #x8208f4c1 #xf50fc457 #x65b0d9c6 #x12b7e950 | ||
| 69 | #x8bbeb8ea #xfcb9887c #x62dd1ddf #x15da2d49 #x8cd37cf3 | ||
| 70 | #xfbd44c65 #x4db26158 #x3ab551ce #xa3bc0074 #xd4bb30e2 | ||
| 71 | #x4adfa541 #x3dd895d7 #xa4d1c46d #xd3d6f4fb #x4369e96a | ||
| 72 | #x346ed9fc #xad678846 #xda60b8d0 #x44042d73 #x33031de5 | ||
| 73 | #xaa0a4c5f #xdd0d7cc9 #x5005713c #x270241aa #xbe0b1010 | ||
| 74 | #xc90c2086 #x5768b525 #x206f85b3 #xb966d409 #xce61e49f | ||
| 75 | #x5edef90e #x29d9c998 #xb0d09822 #xc7d7a8b4 #x59b33d17 | ||
| 76 | #x2eb40d81 #xb7bd5c3b #xc0ba6cad #xedb88320 #x9abfb3b6 | ||
| 77 | #x03b6e20c #x74b1d29a #xead54739 #x9dd277af #x04db2615 | ||
| 78 | #x73dc1683 #xe3630b12 #x94643b84 #x0d6d6a3e #x7a6a5aa8 | ||
| 79 | #xe40ecf0b #x9309ff9d #x0a00ae27 #x7d079eb1 #xf00f9344 | ||
| 80 | #x8708a3d2 #x1e01f268 #x6906c2fe #xf762575d #x806567cb | ||
| 81 | #x196c3671 #x6e6b06e7 #xfed41b76 #x89d32be0 #x10da7a5a | ||
| 82 | #x67dd4acc #xf9b9df6f #x8ebeeff9 #x17b7be43 #x60b08ed5 | ||
| 83 | #xd6d6a3e8 #xa1d1937e #x38d8c2c4 #x4fdff252 #xd1bb67f1 | ||
| 84 | #xa6bc5767 #x3fb506dd #x48b2364b #xd80d2bda #xaf0a1b4c | ||
| 85 | #x36034af6 #x41047a60 #xdf60efc3 #xa867df55 #x316e8eef | ||
| 86 | #x4669be79 #xcb61b38c #xbc66831a #x256fd2a0 #x5268e236 | ||
| 87 | #xcc0c7795 #xbb0b4703 #x220216b9 #x5505262f #xc5ba3bbe | ||
| 88 | #xb2bd0b28 #x2bb45a92 #x5cb36a04 #xc2d7ffa7 #xb5d0cf31 | ||
| 89 | #x2cd99e8b #x5bdeae1d #x9b64c2b0 #xec63f226 #x756aa39c | ||
| 90 | #x026d930a #x9c0906a9 #xeb0e363f #x72076785 #x05005713 | ||
| 91 | #x95bf4a82 #xe2b87a14 #x7bb12bae #x0cb61b38 #x92d28e9b | ||
| 92 | #xe5d5be0d #x7cdcefb7 #x0bdbdf21 #x86d3d2d4 #xf1d4e242 | ||
| 93 | #x68ddb3f8 #x1fda836e #x81be16cd #xf6b9265b #x6fb077e1 | ||
| 94 | #x18b74777 #x88085ae6 #xff0f6a70 #x66063bca #x11010b5c | ||
| 95 | #x8f659eff #xf862ae69 #x616bffd3 #x166ccf45 #xa00ae278 | ||
| 96 | #xd70dd2ee #x4e048354 #x3903b3c2 #xa7672661 #xd06016f7 | ||
| 97 | #x4969474d #x3e6e77db #xaed16a4a #xd9d65adc #x40df0b66 | ||
| 98 | #x37d83bf0 #xa9bcae53 #xdebb9ec5 #x47b2cf7f #x30b5ffe9 | ||
| 99 | #xbdbdf21c #xcabac28a #x53b39330 #x24b4a3a6 #xbad03605 | ||
| 100 | #xcdd70693 #x54de5729 #x23d967bf #xb3667a2e #xc4614ab8 | ||
| 101 | #x5d681b02 #x2a6f2b94 #xb40bbe37 #xc30c8ea1 #x5a05df1b | ||
| 102 | #x2d02ef8d)) | ||
| 103 | |||
| 104 | (define (debuglink-crc32 port) | ||
| 105 | "Compute the 32-bit CRC used in in '.gnu_debuglink' over the data read from | ||
| 106 | PORT and return it." ;(info "(gdb) Separate Debug Files") | ||
| 107 | (let loop ((crc #xffffffff)) | ||
| 108 | (let ((byte (get-u8 port))) | ||
| 109 | (if (eof-object? byte) | ||
| 110 | (logand (lognot crc) #xffffffff) | ||
| 111 | (let* ((index (logand (logxor crc byte) #xff)) | ||
| 112 | (lhs (vector-ref %crc32-table index))) | ||
| 113 | (loop (logxor lhs (ash crc -8)))))))) | ||
| 114 | |||
| 115 | (define (section-contents elf section) ;XXX: copied from linux-modules.scm | ||
| 116 | "Return the contents of SECTION in ELF as a bytevector." | ||
| 117 | (let* ((contents (make-bytevector (elf-section-size section)))) | ||
| 118 | (bytevector-copy! (elf-bytes elf) (elf-section-offset section) | ||
| 119 | contents 0 | ||
| 120 | (elf-section-size section)) | ||
| 121 | contents)) | ||
| 122 | |||
| 123 | (define null-terminated-bytevector->string | ||
| 124 | (compose pointer->string bytevector->pointer)) | ||
| 125 | |||
| 126 | (define (elf-debuglink elf) | ||
| 127 | "Return two values: the '.gnu_debuglink' file name of ELF and its CRC. | ||
| 128 | Return #f for both if ELF lacks a '.gnu_debuglink' section." | ||
| 129 | (let ((section (elf-section-by-name elf ".gnu_debuglink"))) | ||
| 130 | (if section | ||
| 131 | (let ((size (elf-section-size section)) | ||
| 132 | (bv (section-contents elf section)) | ||
| 133 | (endianness (elf-byte-order elf))) | ||
| 134 | (values (null-terminated-bytevector->string bv) | ||
| 135 | (bytevector-u32-ref bv (- size 4) endianness))) | ||
| 136 | (values #f #f)))) | ||
| 137 | |||
| 138 | (define (elf-debuglink-crc-offset elf) | ||
| 139 | "Return the offset of the '.gnu_debuglink' 32-bit CRC, or #f if ELF lacks a | ||
| 140 | '.gnu_debuglink' section." | ||
| 141 | (let ((section (elf-section-by-name elf ".gnu_debuglink"))) | ||
| 142 | (and section | ||
| 143 | (+ (elf-section-offset section) | ||
| 144 | (elf-section-size section) | ||
| 145 | -4)))) | ||
| 146 | |||
| 147 | (define (set-debuglink-crc file debug-file) | ||
| 148 | "Compute the CRC of DEBUG-FILE and set it as the '.gnu_debuglink' CRC in | ||
| 149 | FILE." | ||
| 150 | (let* ((elf (parse-elf (call-with-input-file file get-bytevector-all))) | ||
| 151 | (offset (elf-debuglink-crc-offset elf))) | ||
| 152 | (and offset | ||
| 153 | (let* ((crc (call-with-input-file debug-file debuglink-crc32)) | ||
| 154 | (bv (make-bytevector 4))) | ||
| 155 | (bytevector-u32-set! bv 0 crc (elf-byte-order elf)) | ||
| 156 | (let ((port (open file O_RDWR))) | ||
| 157 | (set-port-position! port offset) | ||
| 158 | (put-bytevector port bv) | ||
| 159 | (close-port port)))))) | ||
| 160 | |||
| 161 | |||
| 162 | ;;; | ||
| 163 | ;;; Updating debuglink CRC. | ||
| 164 | ;;; | ||
| 165 | |||
| 166 | (define (find-elf-files outputs) | ||
| 167 | "Return the list of ELF files found in OUTPUTS, a list of top-level store | ||
| 168 | directories." | ||
| 169 | (define directories | ||
| 170 | (append-map (lambda (output) | ||
| 171 | (list (string-append output "/bin") | ||
| 172 | (string-append output "/sbin") | ||
| 173 | (string-append output "/lib") | ||
| 174 | (string-append output "/libexec"))) | ||
| 175 | outputs)) | ||
| 176 | |||
| 177 | (append-map (lambda (directory) | ||
| 178 | (filter elf-file? | ||
| 179 | (with-error-to-port (%make-void-port "w") | ||
| 180 | (lambda () | ||
| 181 | (find-files directory))))) | ||
| 182 | directories)) | ||
| 183 | |||
| 184 | (define* (graft-debug-links old-outputs new-outputs mapping | ||
| 185 | #:key (log-port (current-error-port))) | ||
| 186 | "Update the '.gnu_debuglink' CRCs found in ELF files of NEW-OUTPUTS, | ||
| 187 | provided NEW-OUTPUTS contains a \"debug\" output, such that those CRCs match | ||
| 188 | those of the corresponding '.debug' files found in the \"debug\" output. | ||
| 189 | |||
| 190 | This procedure is meant to be used as a \"grafting hook\" by (guix build | ||
| 191 | graft)." | ||
| 192 | (match (assoc-ref new-outputs "debug") | ||
| 193 | (#f #t) ;nothing to do | ||
| 194 | (debug-directory | ||
| 195 | (let ((files (find-elf-files (filter-map (match-lambda | ||
| 196 | (("debug" . _) | ||
| 197 | #f) | ||
| 198 | ((name . directory) | ||
| 199 | directory)) | ||
| 200 | new-outputs)))) | ||
| 201 | (for-each (lambda (file) | ||
| 202 | (let ((debug (string-append debug-directory | ||
| 203 | "/lib/debug" file ".debug"))) | ||
| 204 | (when (file-exists? debug) | ||
| 205 | (format log-port | ||
| 206 | "updating '.gnu_debuglink' CRC in '~a'~%" | ||
| 207 | file) | ||
| 208 | (make-file-writable file) | ||
| 209 | (set-debuglink-crc file debug)))) | ||
| 210 | files))))) | ||
diff --git a/guix/build/graft.scm b/guix/build/graft.scm index 8d79e8a50e1..c119ee71d1c 100644 --- a/guix/build/graft.scm +++ b/guix/build/graft.scm | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | 19 | ||
| 20 | (define-module (guix build graft) | 20 | (define-module (guix build graft) |
| 21 | #:use-module (guix build utils) | 21 | #:use-module (guix build utils) |
| 22 | #:use-module (guix build debug-link) | ||
| 22 | #:use-module (rnrs bytevectors) | 23 | #:use-module (rnrs bytevectors) |
| 23 | #:use-module (ice-9 vlist) | 24 | #:use-module (ice-9 vlist) |
| 24 | #:use-module (ice-9 match) | 25 | #:use-module (ice-9 match) |
| @@ -322,8 +323,13 @@ file name pairs." | |||
| 322 | #:directories? #t)) | 323 | #:directories? #t)) |
| 323 | (rename-matching-files output mapping)) | 324 | (rename-matching-files output mapping)) |
| 324 | 325 | ||
| 326 | (define %graft-hooks | ||
| 327 | ;; Default list of hooks run after grafting. | ||
| 328 | (list graft-debug-links)) | ||
| 329 | |||
| 325 | (define* (graft old-outputs new-outputs mapping | 330 | (define* (graft old-outputs new-outputs mapping |
| 326 | #:key (log-port (current-output-port))) | 331 | #:key (log-port (current-output-port)) |
| 332 | (hooks %graft-hooks)) | ||
| 327 | "Apply the grafts described by MAPPING on OLD-OUTPUTS, leading to | 333 | "Apply the grafts described by MAPPING on OLD-OUTPUTS, leading to |
| 328 | NEW-OUTPUTS. MAPPING must be a list of file name pairs; OLD-OUTPUTS and | 334 | NEW-OUTPUTS. MAPPING must be a list of file name pairs; OLD-OUTPUTS and |
| 329 | NEW-OUTPUTS are lists of output name/file name pairs." | 335 | NEW-OUTPUTS are lists of output name/file name pairs." |
| @@ -336,6 +342,10 @@ NEW-OUTPUTS are lists of output name/file name pairs." | |||
| 336 | files)) | 342 | files)) |
| 337 | (match new-outputs | 343 | (match new-outputs |
| 338 | (((names . files) ...) | 344 | (((names . files) ...) |
| 339 | files)))) | 345 | files))) |
| 346 | (for-each (lambda (hook) | ||
| 347 | (hook old-outputs new-outputs mapping | ||
| 348 | #:log-port log-port)) | ||
| 349 | hooks)) | ||
| 340 | 350 | ||
| 341 | ;;; graft.scm ends here | 351 | ;;; graft.scm ends here |
diff --git a/guix/grafts.scm b/guix/grafts.scm index 4b10b3efd74..f303e925f1f 100644 --- a/guix/grafts.scm +++ b/guix/grafts.scm | |||
| @@ -130,7 +130,9 @@ are not recursively applied to dependencies of DRV." | |||
| 130 | #:system system | 130 | #:system system |
| 131 | #:guile-for-build guile | 131 | #:guile-for-build guile |
| 132 | #:modules '((guix build graft) | 132 | #:modules '((guix build graft) |
| 133 | (guix build utils)) | 133 | (guix build utils) |
| 134 | (guix build debug-link) | ||
| 135 | (guix elf)) | ||
| 134 | #:inputs `(,@(map (lambda (out) | 136 | #:inputs `(,@(map (lambda (out) |
| 135 | `("x" ,drv ,out)) | 137 | `("x" ,drv ,out)) |
| 136 | outputs) | 138 | outputs) |
diff --git a/tests/debug-link.scm b/tests/debug-link.scm new file mode 100644 index 00000000000..2dde3cb4607 --- /dev/null +++ b/tests/debug-link.scm | |||
| @@ -0,0 +1,158 @@ | |||
| 1 | ;;; GNU Guix --- Functional package management for GNU | ||
| 2 | ;;; Copyright © 2018 Ludovic Courtès <ludo@gnu.org> | ||
| 3 | ;;; | ||
| 4 | ;;; This file is part of GNU Guix. | ||
| 5 | ;;; | ||
| 6 | ;;; GNU Guix is free software; you can redistribute it and/or modify it | ||
| 7 | ;;; under the terms of the GNU General Public License as published by | ||
| 8 | ;;; the Free Software Foundation; either version 3 of the License, or (at | ||
| 9 | ;;; your option) any later version. | ||
| 10 | ;;; | ||
| 11 | ;;; GNU Guix is distributed in the hope that it will be useful, but | ||
| 12 | ;;; WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;;; GNU General Public License for more details. | ||
| 15 | ;;; | ||
| 16 | ;;; You should have received a copy of the GNU General Public License | ||
| 17 | ;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. | ||
| 18 | |||
| 19 | (define-module (test-debug-link) | ||
| 20 | #:use-module (guix elf) | ||
| 21 | #:use-module (guix build utils) | ||
| 22 | #:use-module (guix build debug-link) | ||
| 23 | #:use-module (guix gexp) | ||
| 24 | #:use-module (guix store) | ||
| 25 | #:use-module (guix tests) | ||
| 26 | #:use-module (guix monads) | ||
| 27 | #:use-module (guix derivations) | ||
| 28 | #:use-module (gnu packages bootstrap) | ||
| 29 | #:use-module (srfi srfi-1) | ||
| 30 | #:use-module (srfi srfi-26) | ||
| 31 | #:use-module (srfi srfi-64) | ||
| 32 | #:use-module (rnrs io ports) | ||
| 33 | #:use-module (ice-9 match)) | ||
| 34 | |||
| 35 | (define %guile-executable | ||
| 36 | (match (false-if-exception (readlink "/proc/self/exe")) | ||
| 37 | ((? string? program) | ||
| 38 | (and (file-exists? program) (elf-file? program) | ||
| 39 | program)) | ||
| 40 | (_ | ||
| 41 | #f))) | ||
| 42 | |||
| 43 | (define read-elf | ||
| 44 | (compose parse-elf get-bytevector-all)) | ||
| 45 | |||
| 46 | (define %store | ||
| 47 | (open-connection-for-tests)) | ||
| 48 | |||
| 49 | (define-syntax-rule (test-assertm name exp) | ||
| 50 | (test-assert name | ||
| 51 | (run-with-store %store exp | ||
| 52 | #:guile-for-build (%guile-for-build)))) | ||
| 53 | |||
| 54 | |||
| 55 | (test-begin "debug-link") | ||
| 56 | |||
| 57 | (unless %guile-executable (test-skip 1)) | ||
| 58 | (test-assert "elf-debuglink" | ||
| 59 | (let ((elf (call-with-input-file %guile-executable read-elf))) | ||
| 60 | (match (call-with-values (lambda () (elf-debuglink elf)) list) | ||
| 61 | ((#f #f) ;no '.gnu_debuglink' section | ||
| 62 | (pk 'no-debuglink #t)) | ||
| 63 | (((? string? file) (? integer? crc)) | ||
| 64 | (string-suffix? ".debug" file))))) | ||
| 65 | |||
| 66 | ;; Since we need %BOOTSTRAP-GCC and co., we have to skip the following tests | ||
| 67 | ;; when networking is unreachable because we'd fail to download it. | ||
| 68 | (unless (network-reachable?) (test-skip 1)) | ||
| 69 | (test-assertm "elf-debuglink" | ||
| 70 | ;; Check whether we can compute the CRC just like objcopy, and whether we | ||
| 71 | ;; can retrieve it. | ||
| 72 | (let* ((code (plain-file "test.c" "int main () { return 42; }")) | ||
| 73 | (exp (with-imported-modules '((guix build utils) | ||
| 74 | (guix build debug-link) | ||
| 75 | (guix elf)) | ||
| 76 | #~(begin | ||
| 77 | (use-modules (guix build utils) | ||
| 78 | (guix build debug-link) | ||
| 79 | (guix elf) | ||
| 80 | (rnrs io ports)) | ||
| 81 | |||
| 82 | (define read-elf | ||
| 83 | (compose parse-elf get-bytevector-all)) | ||
| 84 | |||
| 85 | (setenv "PATH" (string-join '(#$%bootstrap-gcc | ||
| 86 | #$%bootstrap-binutils) | ||
| 87 | "/bin:" 'suffix)) | ||
| 88 | (invoke "gcc" "-O0" "-g" #$code "-o" "exe") | ||
| 89 | (copy-file "exe" "exe.debug") | ||
| 90 | (invoke "strip" "--only-keep-debug" "exe.debug") | ||
| 91 | (invoke "strip" "--strip-debug" "exe") | ||
| 92 | (invoke "objcopy" "--add-gnu-debuglink=exe.debug" | ||
| 93 | "exe") | ||
| 94 | (call-with-values (lambda () | ||
| 95 | (elf-debuglink | ||
| 96 | (call-with-input-file "exe" | ||
| 97 | read-elf))) | ||
| 98 | (lambda (file crc) | ||
| 99 | (call-with-output-file #$output | ||
| 100 | (lambda (port) | ||
| 101 | (let ((expected (call-with-input-file "exe.debug" | ||
| 102 | debuglink-crc32))) | ||
| 103 | (write (list file (= crc expected)) | ||
| 104 | port)))))))))) | ||
| 105 | (mlet* %store-monad ((drv (gexp->derivation "debuglink" exp)) | ||
| 106 | (x (built-derivations (list drv)))) | ||
| 107 | (call-with-input-file (derivation->output-path drv) | ||
| 108 | (lambda (port) | ||
| 109 | (return (match (read port) | ||
| 110 | (("exe.debug" #t) #t) | ||
| 111 | (x (pk 'fail x #f))))))))) | ||
| 112 | |||
| 113 | (unless (network-reachable?) (test-skip 1)) | ||
| 114 | (test-assertm "set-debuglink-crc" | ||
| 115 | ;; Check whether 'set-debuglink-crc' successfully updates the CRC. | ||
| 116 | (let* ((code (plain-file "test.c" "int main () { return 42; }")) | ||
| 117 | (debug (plain-file "exe.debug" "a")) | ||
| 118 | (exp (with-imported-modules '((guix build utils) | ||
| 119 | (guix build debug-link) | ||
| 120 | (guix elf)) | ||
| 121 | #~(begin | ||
| 122 | (use-modules (guix build utils) | ||
| 123 | (guix build debug-link) | ||
| 124 | (guix elf) | ||
| 125 | (rnrs io ports)) | ||
| 126 | |||
| 127 | (define read-elf | ||
| 128 | (compose parse-elf get-bytevector-all)) | ||
| 129 | |||
| 130 | (setenv "PATH" (string-join '(#$%bootstrap-gcc | ||
| 131 | #$%bootstrap-binutils) | ||
| 132 | "/bin:" 'suffix)) | ||
| 133 | (invoke "gcc" "-O0" "-g" #$code "-o" "exe") | ||
| 134 | (copy-file "exe" "exe.debug") | ||
| 135 | (invoke "strip" "--only-keep-debug" "exe.debug") | ||
| 136 | (invoke "strip" "--strip-debug" "exe") | ||
| 137 | (invoke "objcopy" "--add-gnu-debuglink=exe.debug" | ||
| 138 | "exe") | ||
| 139 | (set-debuglink-crc "exe" #$debug) | ||
| 140 | (call-with-values (lambda () | ||
| 141 | (elf-debuglink | ||
| 142 | (call-with-input-file "exe" | ||
| 143 | read-elf))) | ||
| 144 | (lambda (file crc) | ||
| 145 | (call-with-output-file #$output | ||
| 146 | (lambda (port) | ||
| 147 | (write (list file crc) port))))))))) | ||
| 148 | (mlet* %store-monad ((drv (gexp->derivation "debuglink" exp)) | ||
| 149 | (x (built-derivations (list drv)))) | ||
| 150 | (call-with-input-file (derivation->output-path drv) | ||
| 151 | (lambda (port) | ||
| 152 | (return (match (read port) | ||
| 153 | (("exe.debug" crc) | ||
| 154 | (= crc (debuglink-crc32 (open-input-string "a")))) | ||
| 155 | (x | ||
| 156 | (pk 'fail x #f))))))))) | ||
| 157 | |||
| 158 | (test-end "debug-link") | ||
