1# `ipkdbg`: Generate gdb environments from opkg package archives 2 3`ipkdbg` automates the process of generating `gdb` environments for interactive 4debugging and coredump analysis of split-debug binaries by exploiting bitbake's 5runtime package management support outside the context of the BMC. 6 7## Use of `ipkdbg` 8 9Assuming the presence of the [appropriate integration](#theory-of-integration), 10using `ipkdbg` requires minimal fuss. 11 12```text 13SYNOPSIS 14 ipkdbg [-q] RELEASE FILE CORE [PACKAGE...] 15``` 16 17It handles the following use-cases: 18 19### Core Dump Analysis 20 21After extracting a core file from the BMC an interactive `gdb` session can be 22set up against it with: 23 24```sh 25$ ipkdbg 2.11.0 - my-application.core 26... 27(gdb) 28``` 29 30Where: 31 321. `ipkdbg` is the script 332. `2.11.0` is the OpenBMC version tag that locates the appropriate `opkg.conf` 343. `-` is the FILE parameter. `-` specifies it must be extracted from the core 354. `my-application.core` is a core dump generated by `/usr/bin/my-application` 36 37Note that for convenience `ipkdbg` automatically runs `bt` in the `gdb` session 38once the core has been loaded to provide a backtrace. 39 40Note that we don't need to specify any packages to install into the rootfs _if_ 41the image package database is available. `ipkdbg` will perform a reverse-lookup 42to map the absolute binary path extracted from the core to the package that 43installed it. From there `opkg` will resolve all the dependencies. Additionally, 44`ipkdbg` will identify the associated debug symbol and source packages and 45install them as well. 46 47If an image package database is not available then `ipkdbg` will require that 48the necessary packages are listed on the command-line. 49 50### Scripted Backtrace Extraction 51 52For use in scripting environments to automate backtrace extraction `ipkdbg` has 53the `-q` option to quit `gdb` immediately after the backtrace is printed. The 54invocation looks like: 55 56```sh 57ipkdbg -q 2.11.0 - my-application.core 58``` 59 60### Interactive debug 61 62Interactive debugging is handled by attaching `gdbserver` on the BMC to the 63running instance of `/usr/bin/my-application` on the BMC. `ipkdbg` is then used 64to generate the `gdb` environment: 65 66```sh 67$ ipkdbg 2.11.0 /usr/bin/my-application - 68... 69(gdb) 70``` 71 72Where: 73 741. `ipkdbg` is the script 752. `2.11.0` is the OpenBMC version tag that locates the appropriate `opkg.conf` 763. `/usr/bin/my-application` is the absolute path of the application to debug 774. `-` is the CORE parameter. `-` specifies that there is no core file 78 79Note that we don't need to specify any packages to install into the rootfs _if_ 80the image package database is available. `ipkdbg` will perform a reverse-lookup 81to map the absolute binary path provided on the command-line to the package that 82installed it. From there `opkg` will resolve all the dependencies. Additionally, 83`ipkdbg` will identify the associated debug symbol and source packages and 84install them as well. 85 86If an image package database is not available then `ipkdbg` will require that 87the necessary packages are listed on the command-line. 88 89Once the `(gdb)` prompt is reached the usual remote debugging command applies: 90 91```text 92(gdb) target remote $BMC:1234 93``` 94 95### Whoops, I Forgot A Package 96 97To save exiting the `gdb` session and re-invoking `ipkdbg` to add a package to 98the rootfs environment, `ipkdbg` installs an `opkg` helper into the PATH of the 99`gdb` process. With this, you can drop to a shell from `gdb` via the `sh` 100command, and then run `opkg install ...` to install the necessary packages. Exit 101the shell subprocess to return to your `gdb` prompt with the new package 102included in the `gdb` environment. 103 104## Theory of Maintenance 105 106`ipkdbg` is intended to operate with minimal assumptions about its environment. 107The assumptions it does make are: 108 1091. It's running in a POSIX environment with access to 110 1. `coreutils` 111 2. `awk` 112 3. `tar` 113 4. `gzip` 114 5. `wget` 1152. A multi-arch capable `gdb` is installed 116 117However, `ipkdbg` also relies on `opkg` to get its job done. As `opkg` is itself 118a package manager, it tends not to be available as a package via distro package 119managers. A conflicting requirement is that we want `ipkdbg` to be able to run 120almost anywhere without fuss. To resolve these issues `ipkdbg` packages `opkg` 121binaries inside itself as a self-extracting shell-script. What you see in this 122directory is the input script ([`ipkdbg.in`](ipkdbg.in)) and build 123infrastructure ([`Makefile`](Makefile)) for generating an `ipkdbg` executable 124that packages one or more `opkg` binaries. 125 126`ipkdbg` supports multiple distros and architectures by defining a directory 127scheme to contain `opkg` binaries. This hierarchy is archived and compressed 128using `tar` and `gzip`, and the archive embedded in the `ipkdbg` shell script by 129the [`Makefile`](Makefile). The `opkg` path for a given architecture, distro and 130release combination is defined by the following directory hierarchy in terms of 131[`os-release(5)`][os-release]: 132 133[os-release]: 134 https://www.man7.org/linux/man-pages/man5/os-release.5.html#OPTIONS 135 136```sh 137$(uname -m)/${ID}/${VERSION_ID}/opkg 138``` 139 140This hierarchy must be placed under a `bin/` directory alongside the 141[`Makefile`](Makefile). 142 143To avoid licensing and distribution legal issues openbmc-tools does not provide 144pre-built `opkg` binaries. You must build your own and integrate them into the 145hierarchy under `bin/` outlined above. To this end, 146[the `build-opkg` script is provided](build-opkg). It probably won't work 147without tinkering for your target distro, but it might get you 90% of the way 148there. 149 150## Maintenance in Practice 151 152Once you have built the required `opkg` binaries and integrated them into the 153hierarchy under `bin/` alongside the `Makefile`, run `make` to generate the 154final `ipkdbg` script. The output script can then be freely copied between 155machines supported by the embedded `opkg` binaries. The build system will handle 156stripping the `opkg` binaries to ensure their size is reduced as much as 157practical prior to archiving and compression. It is worth committing the 158binaries under `bin/` to ensure that the build for your output `ipkdbg` script 159is reproducible. 160 161## Theory of Integration 162 163For `ipkdbg` to do its job via `opkg` it must be possible for it to acquire an 164`opkg.conf` that describes the location of the package archive for your target 165environment. The `IPKDBG_CONF_*` variables help describe a `wget`-compatible URL 166where this configuration lives. `ipkdbg` will bootstrap by fetching this 167`opkg.conf` and then passing it as a parameter to all invocations of `opkg`, 168where these invocations of `opkg` populate a rootfs used as your `gdb` debugging 169environment. 170 171A consequence of this is you must also host `ipk` package archives whose URLs 172can be described in the acquired `opkg.conf`. You will need one complete package 173archive per BMC target environment (tag or release). 174 175The packages can be extracted from the bitbake build tree by archiving 176`tmp/deploy/ipk` once `bitbake obmc-phosphor-image && bitbake package-index` has 177exited successfully. 178 179Finally, `ipkdbg` works best when it has access to the image's installed package 180database. This can be captured from the build tree when the build is configured 181with [`INC_IPK_IMAGE_GEN = "1"`][incremental-builds] by archiving the directory 182hierarchy under `./tmp/work/*/obmc-phosphor-image/1.0-r0/temp/saved` with the 183following incantation: 184 185```sh 186tar -cJf opkg-database.tar.xz \ 187 -C ./tmp/work/*/obmc-phosphor-image/1.0-r0/temp/saved/target/ \ 188 info lists status 189``` 190 191`ipkdbg` assumes that the appropriate `opkg-database.tar.xz` can be fetched 192using `wget` and that its URL can be generated in the same manner as that for 193`opkg.conf`. 194 195[incremental-builds]: 196 https://git.openembedded.org/openembedded-core/commit/?id=adf587e55c0f9bc74f0bef415273c937401baebb 197