addr2line-0.10.0/.gitignore010066400017500001750000000000411332105314100136330ustar0000000000000000target Cargo.lock *.png tmp.* *~ addr2line-0.10.0/.travis.yml010066400017500001750000000013721342671150200137740ustar0000000000000000language: rust cache: cargo sudo: false addons: apt: packages: - binutils before_script: - export RUST_BACKTRACE=1 script: ./ci/script.sh os: - linux - osx rust: - nightly - beta - stable env: - GIMLI_JOB="build" - GIMLI_JOB="features" matrix: fast_finish: true include: # Coverage should only run on Linux and stable Rust. - rust: stable os: linux sudo: required env: GIMLI_JOB="coverage" # Building docs only needs to happen on one os and only on stable. - rust: stable os: linux env: GIMLI_JOB="doc" # Benching should only happen on nightly. - rust: nightly env: GIMLI_JOB="bench" # Some features require nightly. - rust: nightly env: GIMLI_JOB="nightly_features" addr2line-0.10.0/CHANGELOG.md010066400017500001750000000021431351061473000134700ustar0000000000000000## 0.10.0 (2019/07/07) ### Breaking changes * [#127](https://github.com/gimli-rs/addr2line/pull/127) Update `gimli`. ## 0.9.0 (2019/05/02) ### Breaking changes * [#121](https://github.com/gimli-rs/addr2line/pull/121) Update `gimli`, `object`, and `fallible-iterator` dependencies. ### Added * [#121](https://github.com/gimli-rs/addr2line/pull/121) Reexport `gimli`, `object`, and `fallible-iterator`. ## 0.8.0 (2019/02/06) ### Breaking changes * [#107](https://github.com/gimli-rs/addr2line/pull/107) Update `object` dependency to 0.11. This is part of the public API. ### Added * [#101](https://github.com/gimli-rs/addr2line/pull/101) Add `object` feature (enabled by default). Disable this feature to remove the `object` dependency and `Context::new` API. * [#102](https://github.com/gimli-rs/addr2line/pull/102) Add `std` (enabled by default) and `alloc` features. ### Changed * [#108](https://github.com/gimli-rs/addr2line/issues/108) `demangle` no longer ouputs the hash for rust symbols. * [#109](https://github.com/gimli-rs/addr2line/issues/109) Set default `R` for `Context`. addr2line-0.10.0/Cargo.toml.orig010066400017500001750000000031411351061473000145450ustar0000000000000000[package] authors = ["Nick Fitzgerald ", "Philip Craig ", "Jon Gjengset ", "Noah Bergbauer "] description = "A cross-platform symbolication library written in Rust, using `gimli`" documentation = "https://docs.rs/addr2line" keywords = ["DWARF", "debug", "elf", "symbolicate", "atos"] categories = ["development-tools::debugging", "command-line-utilities"] license = "Apache-2.0/MIT" name = "addr2line" readme = "./README.md" repository = "https://github.com/gimli-rs/addr2line" version = "0.10.0" exclude = ["/benches/*", "/fixtures/*"] [badges] travis-ci = { repository = "gimli-rs/addr2line" } [dependencies] gimli = { version = "0.19", default-features = false, features = ["read"] } fallible-iterator = { version = "0.2", default-features = false } object = { version = "0.12", default-features = false, optional = true } intervaltree = { version = "0.2", default-features = false } smallvec = { version = "0.6", default-features = false } lazycell = "1.0" rustc-demangle = { version = "0.1", optional = true } cpp_demangle = { version = "0.2", default-features = false, optional = true } [dev-dependencies] memmap = "0.7" clap = "2" backtrace = "0.3.13" findshlibs = "0.5" rustc-test = "0.3" [profile.release] debug = true [profile.bench] debug = true [features] default = ["rustc-demangle", "cpp_demangle", "std-object"] std = ["gimli/std", "intervaltree/std", "smallvec/std"] std-object = ["std", "object", "object/std"] alloc = ["gimli/alloc"] [[test]] name = "output_equivalence" harness = false [[test]] name = "correctness" addr2line-0.10.0/Cargo.toml0000644000000044410000000000000110160ustar00# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] name = "addr2line" version = "0.10.0" authors = ["Nick Fitzgerald ", "Philip Craig ", "Jon Gjengset ", "Noah Bergbauer "] exclude = ["/benches/*", "/fixtures/*"] description = "A cross-platform symbolication library written in Rust, using `gimli`" documentation = "https://docs.rs/addr2line" readme = "./README.md" keywords = ["DWARF", "debug", "elf", "symbolicate", "atos"] categories = ["development-tools::debugging", "command-line-utilities"] license = "Apache-2.0/MIT" repository = "https://github.com/gimli-rs/addr2line" [profile.bench] debug = true [profile.release] debug = true [[test]] name = "output_equivalence" harness = false [[test]] name = "correctness" [dependencies.cpp_demangle] version = "0.2" optional = true default-features = false [dependencies.fallible-iterator] version = "0.2" default-features = false [dependencies.gimli] version = "0.19" features = ["read"] default-features = false [dependencies.intervaltree] version = "0.2" default-features = false [dependencies.lazycell] version = "1.0" [dependencies.object] version = "0.12" optional = true default-features = false [dependencies.rustc-demangle] version = "0.1" optional = true [dependencies.smallvec] version = "0.6" default-features = false [dev-dependencies.backtrace] version = "0.3.13" [dev-dependencies.clap] version = "2" [dev-dependencies.findshlibs] version = "0.5" [dev-dependencies.memmap] version = "0.7" [dev-dependencies.rustc-test] version = "0.3" [features] alloc = ["gimli/alloc"] default = ["rustc-demangle", "cpp_demangle", "std-object"] std = ["gimli/std", "intervaltree/std", "smallvec/std"] std-object = ["std", "object", "object/std"] [badges.travis-ci] repository = "gimli-rs/addr2line" addr2line-0.10.0/LICENSE-APACHE010066400017500001750000000251371332105314100136040ustar0000000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. addr2line-0.10.0/LICENSE-MIT010066400017500001750000000020551332105314100133060ustar0000000000000000Copyright (c) 2016-2018 The gimli Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. addr2line-0.10.0/README.md010066400017500001750000000061741332105314100131370ustar0000000000000000# addr2line [![](http://meritbadge.herokuapp.com/addr2line) ![](https://img.shields.io/crates/d/addr2line.svg)](https://crates.io/crates/addr2line) [![](https://docs.rs/addr2line/badge.svg)](https://docs.rs/addr2line/) [![Build Status](https://travis-ci.org/gimli-rs/addr2line.svg?branch=master)](https://travis-ci.org/gimli-rs/addr2line) [![Coverage Status](https://coveralls.io/repos/github/gimli-rs/addr2line/badge.svg?branch=master)](https://coveralls.io/github/gimli-rs/addr2line?branch=master) A cross-platform library for retrieving per-address debug information from executables with DWARF debug symbols. `addr2line` uses [`gimli`](https://github.com/gimli-rs/gimli) to parse the debug symbols of an executable, and exposes an interface for finding the source file, line number, and wrapping function for instruction addresses within the target program. These lookups can either be performed programmatically through `Context::find_location` and `Context::find_frames`, or via the included example binary, `addr2line` (named and modelled after the equivalent utility from [GNU binutils](https://sourceware.org/binutils/docs/binutils/addr2line.html)). # Quickstart - Add the [`object` crate](https://crates.io/crates/object) to your `Cargo.toml` - Add the [`addr2line` crate](https://crates.io/crates/addr2line) to your `Cargo.toml` - Add `extern crate object` and `extern crate addr2line` to your main crate entry file - Load the file and parse it with [`object::File::parse`](https://docs.rs/object/*/object/struct.File.html#method.parse) - Pass the parsed file to [`addr2line::Context::new` ](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.new) - Use [`addr2line::Context::find_location`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_location) or [`addr2line::Context::find_frames`](https://docs.rs/addr2line/*/addr2line/struct.Context.html#method.find_frames) to look up debug information for an address # Performance The library aims to perform similarly to equivalent existing tools such as `addr2line` from binutils, `eu-addr2line` from elfutils, and `llvm-symbolize` from the llvm project. Currently the library optimizes for memory over for speed when parsing line number sequences. In particular, the algorithm used can be slow for large line sequences, but uses much less memory. Note that LLVM generates one line sequence per function, but gcc can include multiple functions in each line sequence. We haven't done extensive benchmarking (yet), but the runtime and memory use results we observe for one relatively large Rust application are quite promising: ![addr2line runtime](time.png) ![addr2line memory](memory.png) ## License Licensed under either of * Apache License, Version 2.0 ([`LICENSE-APACHE`](./LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0) * MIT license ([`LICENSE-MIT`](./LICENSE-MIT) or http://opensource.org/licenses/MIT) at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. addr2line-0.10.0/bench.plot.r010066400017500001750000000017501332105314100140720ustar0000000000000000v <- read.table(file("stdin")) t <- data.frame(prog=v[,1], funcs=(v[,2]=="func"), time=v[,3], mem=v[,4], stringsAsFactors=FALSE) t$prog <- as.character(t$prog) t$prog[t$prog == "master"] <- "gimli-rs/addr2line" t$funcs[t$funcs == TRUE] <- "With functions" t$funcs[t$funcs == FALSE] <- "File/line only" t$mem = t$mem / 1024.0 library(ggplot2) p <- ggplot(data=t, aes(x=prog, y=time, fill=prog)) p <- p + geom_bar(stat = "identity") p <- p + facet_wrap(~ funcs) p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank()) p <- p + ylab("time (s)") + ggtitle("addr2line runtime") ggsave('time.png',plot=p,width=10,height=6) p <- ggplot(data=t, aes(x=prog, y=mem, fill=prog)) p <- p + geom_bar(stat = "identity") p <- p + facet_wrap(~ funcs) p <- p + theme(axis.title.x=element_blank(), axis.text.x=element_blank(), axis.ticks.x=element_blank()) p <- p + ylab("memory (kB)") + ggtitle("addr2line memory usage") ggsave('memory.png',plot=p,width=10,height=6) addr2line-0.10.0/benchmark.sh010077500017500001750000000060121332105314100141400ustar0000000000000000#!/bin/bash if [[ $# -le 1 ]]; then echo "Usage: $0 [] REFS..." exit 1 fi target="$1" shift addresses="" if [[ -e "$1" ]]; then addresses="$1" shift fi # path to "us" # readlink -f, but more portable: dirname=$(perl -e 'use Cwd "abs_path";print abs_path(shift)' "$(dirname "$0")") # http://stackoverflow.com/a/2358432/472927 { # compile all refs pushd "$dirname" > /dev/null # if the user has some local changes, preserve them nstashed=$(git stash list | wc -l) echo "==> Stashing any local modifications" git stash --keep-index > /dev/null popstash() { # http://stackoverflow.com/q/24520791/472927 if [[ "$(git stash list | wc -l)" -ne "$nstashed" ]]; then echo "==> Restoring stashed state" git stash pop > /dev/null fi } # if the user has added stuff to the index, abort if ! git diff-index --quiet HEAD --; then echo "Refusing to overwrite outstanding git changes" popstash exit 2 fi current=$(git symbolic-ref --short HEAD) for ref in "$@"; do echo "==> Compiling $ref" git checkout -q "$ref" commit=$(git rev-parse HEAD) fn="target/release/addr2line-$commit" if [[ ! -e "$fn" ]]; then cargo build --release --example addr2line cp target/release/examples/addr2line "$fn" fi if [[ "$ref" != "$commit" ]]; then ln -sfn "addr2line-$commit" target/release/addr2line-"$ref" fi done git checkout -q "$current" popstash popd > /dev/null # get us some addresses to look up if [[ -z "$addresses" ]]; then echo "==> Looking for benchmarking addresses (this may take a while)" addresses=$(mktemp tmp.XXXXXXXXXX) objdump -C -x --disassemble -l "$target" \ | grep -P '0[048]:' \ | awk '{print $1}' \ | sed 's/:$//' \ > "$addresses" echo " -> Addresses stored in $addresses; you should re-use it next time" fi run() { func="$1" name="$2" cmd="$3" args="$4" printf "%s\t%s\t" "$name" "$func" if [[ "$cmd" =~ llvm-symbolizer ]]; then /usr/bin/time -f '%e\t%M' "$cmd" $args -obj="$target" < "$addresses" 2>&1 >/dev/null else /usr/bin/time -f '%e\t%M' "$cmd" $args -e "$target" < "$addresses" 2>&1 >/dev/null fi } # run without functions log1=$(mktemp tmp.XXXXXXXXXX) echo "==> Benchmarking" run nofunc binutils addr2line >> "$log1" #run nofunc elfutils eu-addr2line >> "$log1" run nofunc llvm-sym llvm-symbolizer -functions=none >> "$log1" for ref in "$@"; do run nofunc "$ref" "$dirname/target/release/addr2line-$ref" >> "$log1" done cat "$log1" | column -t # run with functions log2=$(mktemp tmp.XXXXXXXXXX) echo "==> Benchmarking with -f" run func binutils addr2line "-f -i" >> "$log2" #run func elfutils eu-addr2line "-f -i" >> "$log2" run func llvm-sym llvm-symbolizer "-functions=linkage -demangle=0" >> "$log2" for ref in "$@"; do run func "$ref" "$dirname/target/release/addr2line-$ref" "-f -i" >> "$log2" done cat "$log2" | column -t cat "$log2" >> "$log1"; rm "$log2" echo "==> Plotting" Rscript --no-readline --no-restore --no-save "$dirname/bench.plot.r" < "$log1" echo "==> Cleaning up" rm "$log1" exit 0 } addr2line-0.10.0/ci/script.sh010077500017500001750000000023671346220724300141300ustar0000000000000000#!/usr/bin/env bash set -ex case "$GIMLI_JOB" in "build") if [ "$TRAVIS_OS_NAME" = "linux" ]; then cargo test cargo test --release else cargo build cargo build --release fi ;; "features") cargo build --no-default-features --features "std" cargo build --no-default-features --features "std cpp_demangle" cargo build --no-default-features --features "std rustc-demangle" cargo build --no-default-features --features "std-object" ;; "nightly_features") cargo build --no-default-features --features "alloc" cargo build --no-default-features --features "alloc object" ;; "doc") cargo doc ;; "bench") cargo bench ;; "coverage") RUSTFLAGS="--cfg procmacro2_semver_exempt" cargo install --force cargo-tarpaulin cargo tarpaulin --verbose --ciserver travis-ci --coveralls "$TRAVIS_JOB_ID"; ;; "cross") rustup target add $TARGET cargo install cross --force cross test --target $TARGET $GIMLI_PROFILE --features "$GIMLI_FEATURES" ;; *) echo "Error! Unknown \$GIMLI_JOB: $GIMLI_JOB" exit 1 esac addr2line-0.10.0/coverage010077500017500001750000000013241332105314100133710ustar0000000000000000#!/usr/bin/env bash # # Usage: # ./coverage # # Run kcov on the tests, and merge the results. # # Environment variables: # TRAVIS_JOB_ID - id for coveralls, defaults to none # KCOV - path to kcov, defaults to 'kcov' [ -n "$TRAVIS_JOB_ID" ] && COVERALLS_ID="--coveralls-id=$TRAVIS_JOB_ID" [ -z "$KCOV" ] && KCOV=kcov # Rebuild tests with dead code included, and get a list of the filenames. export RUSTFLAGS="-C link-dead-code" TEST_FILES=$(cargo test 2>&1 >/dev/null | awk '/^ Running target\/debug\// { print $2 }') KCOV_OPTS="--verify --exclude-pattern=/.cargo" OUT_DIR=target/kcov for f in $TEST_FILES; do "$KCOV" $KCOV_OPTS "$OUT_DIR" $f done "$KCOV" --merge $KCOV_OPTS $COVERALLS_ID "$OUT_DIR" "$OUT_DIR" addr2line-0.10.0/examples/addr2line.rs010066400017500001750000000163051332105314100157050ustar0000000000000000extern crate addr2line; extern crate clap; extern crate fallible_iterator; extern crate gimli; extern crate memmap; extern crate object; use std::fs::File; use std::path::Path; use std::io::{BufRead, Lines, StdinLock}; use std::borrow::Cow; use clap::{App, Arg, Values}; use fallible_iterator::FallibleIterator; use object::Object; use addr2line::{Context, Location}; fn parse_uint_from_hex_string(string: &str) -> u64 { if string.len() > 2 && string.starts_with("0x") { u64::from_str_radix(&string[2..], 16).expect("Failed to parse address") } else { u64::from_str_radix(string, 16).expect("Failed to parse address") } } enum Addrs<'a> { Args(Values<'a>), Stdin(Lines>), } impl<'a> Iterator for Addrs<'a> { type Item = u64; fn next(&mut self) -> Option { let text = match *self { Addrs::Args(ref mut vals) => vals.next().map(Cow::from), Addrs::Stdin(ref mut lines) => lines.next().map(Result::unwrap).map(Cow::from), }; text.as_ref() .map(Cow::as_ref) .map(parse_uint_from_hex_string) } } fn print_loc(loc: &Option, basenames: bool, llvm: bool) { if let Some(ref loc) = *loc { let file = loc.file.as_ref().unwrap(); let path = if basenames { Path::new(Path::new(file).file_name().unwrap()) } else { Path::new(file) }; print!("{}:", path.display()); if llvm { print!("{}:{}", loc.line.unwrap_or(0), loc.column.unwrap_or(0)); } else if let Some(line) = loc.line { print!("{}", line); } else { print!("?"); } println!(); } else if llvm { println!("??:0:0"); } else { println!("??:0"); } } fn print_function(name: &str, language: Option, demangle: bool) { if demangle { print!("{}", addr2line::demangle_auto(Cow::from(name), language)); } else { print!("{}", name); } } fn main() { let matches = App::new("hardliner") .version("0.1") .about("A fast addr2line clone") .arg( Arg::with_name("exe") .short("e") .long("exe") .value_name("filename") .help( "Specify the name of the executable for which addresses should be translated.", ) .required(true), ) .arg( Arg::with_name("functions") .short("f") .long("functions") .help("Display function names as well as file and line number information."), ) .arg( Arg::with_name("pretty") .short("p") .long("pretty-print") .help( "Make the output more human friendly: each location are printed on \ one line.", ), ) .arg(Arg::with_name("inlines").short("i").long("inlines").help( "If the address belongs to a function that was inlined, the source \ information for all enclosing scopes back to the first non-inlined \ function will also be printed.", )) .arg( Arg::with_name("addresses") .short("a") .long("addresses") .help( "Display the address before the function name, file and line \ number information.", ), ) .arg( Arg::with_name("basenames") .short("s") .long("basenames") .help("Display only the base of each file name."), ) .arg(Arg::with_name("demangle").short("C").long("demangle").help( "Demangle function names. \ Specifying a specific demangling style (like GNU addr2line) \ is not supported. (TODO)", )) .arg( Arg::with_name("llvm") .long("llvm") .help("Display output in the same format as llvm-symbolizer."), ) .arg( Arg::with_name("addrs") .takes_value(true) .multiple(true) .help("Addresses to use instead of reading from stdin."), ) .get_matches(); let do_functions = matches.is_present("functions"); let do_inlines = matches.is_present("inlines"); let pretty = matches.is_present("pretty"); let print_addrs = matches.is_present("addresses"); let basenames = matches.is_present("basenames"); let demangle = matches.is_present("demangle"); let llvm = matches.is_present("llvm"); let path = matches.value_of("exe").unwrap(); let file = File::open(path).unwrap(); let map = unsafe { memmap::Mmap::map(&file).unwrap() }; let file = &object::File::parse(&*map).unwrap(); let symbols = file.symbol_map(); let ctx = Context::new(file).unwrap(); let stdin = std::io::stdin(); let addrs = matches .values_of("addrs") .map(Addrs::Args) .unwrap_or_else(|| Addrs::Stdin(stdin.lock().lines())); for probe in addrs { if print_addrs { if llvm { print!("0x{:x}", probe); } else { print!("0x{:016x}", probe); } if pretty { print!(": "); } else { println!(); } } if do_functions || do_inlines { let mut printed_anything = false; let mut frames = ctx.find_frames(probe).unwrap().enumerate(); while let Some((i, frame)) = frames.next().unwrap() { if pretty && i != 0 { print!(" (inlined by) "); } if do_functions { if let Some(func) = frame.function { print_function(&func.raw_name().unwrap(), func.language, demangle); } else { print!("??"); } if pretty { print!(" at "); } else { println!(); } } print_loc(&frame.location, basenames, llvm); printed_anything = true; if !do_inlines { break; } } if !printed_anything { if do_functions { if let Some(name) = symbols.get(probe).and_then(|x| x.name()) { print_function(name, None, demangle); } else { print!("??"); } if pretty { print!(" "); } else { println!(); } } if llvm { println!("??:0:0"); } else { println!("??:0"); } } } else { let loc = ctx.find_location(probe).unwrap(); print_loc(&loc, basenames, llvm); } if llvm { println!(); } } } addr2line-0.10.0/memory.png010066400017500001750000002105361332105314100136750ustar0000000000000000PNG  IHDR #/ pHYs.#.#x?v IDATxy\Tæb( KkKZYZhI[쓙٢eY**(" /3 9=ι}=ʝμ3Z-ǝe`HI Q&De`HI Q&De`HI Q&De`HI Q&De`HI Q&De`HPl߾L '<<\9l͛1Ga?̴{ٹxxx{\`HKKK 9qDqqreΝ8gOOOcLK/>;wÇ5d%%%O^r/mq "Q&&&cǎqiii_uΝ/]T cGRRҐ!C޽[V믿|}}}h''֭[U[[jw1e@%ckk;yI&gff^tiݛ7o.((Ӈ r9''}ѣG `%Ѓ?066VO>W^ݰa6mjmm1x_v-88X|ƍv &D>L駟>t萇G񞞞aaaÇWn\vmrrG &D|eKKmkZZZn۶]RTTbQ-V322 |||jsZZZJJJJJm+w^eu 6ŋ.\(oٽ{x(--;w2225jifffq\w޹sܼQFIR%%%efffee:;;7mֶ]DBQXX?=zΝ;{ڶm;t)So߾߸qcͿKbbrŠA} &ԫWz#oׯ_m۶578srr֬Y˗/=sׯv(;8q7n23ҥK:6԰{ѣG#GO#իrO9MLL̆ .^jccӰaΝ;8pƽ`޽!!!GnnrWF 0}ȗW_fff?{[nXXXxxxhbɣG.{Ň_Ο?иqݻ3駟z&u4/^cǎݻwij߾#ƏKWU{o޼y-WgϞc[ WQ__WJR]rE6lP9T=zm۶_5***''G¢CÇ={woз!ݻwo߾o߾doo6mL>}?qVV۷.6J{xx1eʔ;wyAA+*SNqqqjVn?uT-wϗ5jHkĉҮlvggg/ZnРy^^F[n-Ihh2ȑ#ec !߿/mOHHѣ wߕ~RkѢ>%AAATT}?Fi̙3[2Dc]yiii?|(xgo߾]iUܸ͛sNG#Qm/øz.җJ!"""ڵkwߩTb]֧OL#]WPg(ұcڵ _>yR-1C 9uꔎ}7.>>^`vٳ#G<UZ夠@^[DRVÇ K~f1%%%ӧOouCiiE/_{*QTSL?*,**zܹ~ h._g}VwsM~'O0`@ffc/jL7\tn v4x`7xcƍvZnU!Ĝ9stO<N3ުO'T>jhB?~>Ѹq㰰rOe|E/};۳?k(Q^LՊEF秽I͕vh~A{ZڰaC6p裏.]Vݻ7|pJ%o ׯQzOsN(YZZ]V%55Ȉs:_^# HCNk 6dee4={349R~Ev Xzjժ!Chy={~tY]~u2JHHPVK;rc;euĈCQFӧ0v^7|zm+2tk׮)7~Kڜ9sZn=sosss [n[[[W:ɓ'+/((믿*mU%K.`ffLGrΒrj4=z}vQ֬Y˟UW ܏Y8;w1ԩSuܽ{WYmժxkkW^ye9rd^^^0ýǟtHew޺Obkk`ճgWUY=ZdI6m~W]ʦM;i.Օƪ%=zнr]fȨAkRV-_cFJN[nʪ.2ߏ:?+ӦMӥs# #G|饗ks:DGGۻx]˫˯<.#Q@rrrΟ??,\EK,IJJX#rnݺM4T 6~G]_|QY2B&M諫+W(KTJyvvUrAu^jޤZ&:ͤ$lmm]RMJ-[ׯ_cpprn]v]'HV+ecbmmk)~AAA+Vxїj$&&*k׮Ҙ2C'N$&&^zUojjjU;yڴi*56Vrvvj9s={ &[ͭ&DNc%)]"77f#2>&YYYrqʵl*eaa)/"ߏVVVG޸qTyfLLƜRʥ&L w9yc4GEEEEE-[~AAA{}hP#/ںJ㱵5V4ϟ \nƀ4iiӦgWvvvXLᚔժޏB{{{\\\\AU LٹsrJھ}\ѣͷ~=vX=55uڵݻw2dիWwD;;;*M[1 3kڵ ,hw[N:կ_֬YǏҧƂ>U1''X͛_z饢" ,Yd6660ZLwU:\C^^^͆S'5177wppoj_&]gٴiTrJ||T=~;wS2JѣGueϞ=}-7ojP4^E2 2 -رc{ѽ{w77jtƌ2Vz矿kLv]q46A&rM4h '<|͕M2n89QFsΥKJ~I9uTG"7nܸq㊊?~رy>3fLLL.hZxUie@Xz 0Ejzٲe-6m|~8bĈjgu*W\RDcu^s6mȒ߶mg!\\\Քc0k)55Jsr'''U8prv EEEʕvڪU+^z=zXxyW^yQb {;]R߿o)#Q0EGnnn3f̰鬓;vTVܹs꼆Ο?/+tŋ#F0A֭[+|]-L暴iF.^tI/_VΡbTz5J;w͛B+Rt2BT}ueiiٷo/ʕ+T_U*r<<<Ջ/ƍcL.zG `"##_iӦ4,))ЪU+'N}TyMΜ9SСC5y\u]Y3H&]vUV9{Ç+ݺuϘq)dii9qDC4^_~y'-YYYׯ_r\=4lP?^奢+1 2)JJJRV5֢Վͻt"Wwءc?Sii:U__ߐ;;; W\ꫯtǎVXjaXL)۶mӽ֭[U}4h2nΝ999eȐ!dC%l222:nW%==]Y5ہY=jNNNXX+ƪe@HL^^^z.kghLT"77>3nզ lll wzذar5>>~߾}:]reB~ 2Zg"פk׮7f{H:-suuٳ'D/:u믿VhL6UecǎiqqqQٳgt~;0`w{JL.zG `\\\J'B3fT9qD[[[z?ZbEJJq;۷o:uJ@ǪΝ.X ##VM4 ̙3[,XPiF~~2k,kkkOW_R\utt1bޏ'wj7ި[33͛UJ-jZcI&M(};:u{޽ϵ|r]:q#Q0Eʪr!r.Y$44TQV8}tUV}Z߲e+_ј駟6ܱkN^~}ر>$22R X`XL̚5K9aIBB¤IJJJ*/))4i˗-/FSO988UeƸq 1SFoҥKZ?3]&P"\"? IDATB 4HY׿{wԠAeA}YӧjϞ=_ҕL.E ` nܸqǎߺukȑesM4쐭\aÆ-/Y2335"sssx3f>xv^ ΝSV[2lÆ رceA/**Z~!Crrr/b- V5iڴᆱܲw~%&& NLL۷F*Ʋe||| 7Bkk#G@.uBOydhh-[0lܹsggg]\\I&)7nܸq֭#GԩSƍ333cccCBB>QQQ~^;WCLLz Uՠ[n?Cy=hРVZ;y殮׮]۳gϭ[m̶l٢`"_Whhٳg-mڴ8pSO=%HNN /--U \xG8nܸm۶il2*iÇ߳g%..cǎ۷o6mRRR7mt5)fȑ6ms߾} p!y˥Kuֹs9;;?x ))ʕ+v_%go͚5[fW\ҥ˴iӦLҦM 6ȋIJU-)D&r}R0Iϟ.1Avvveϝ;e[!>*=nZrԩoΣJ65Ѯ]j܏SNj"YxqzEBBBE/رcvv̙3-K.gWWת^j!GBBB}J<III;whu`ݕaÆuի3224fk֬e<҂,666:ߠNRU ~mJ(9;;믆^ˈL䚸=zJѣfNj#jjΝ:@oeSy*y߾}5x?ުUlsennn{V}Q*(#G9s&00PK/xUi[[>LC,XŋZbիoK_?/ ڹ222juѢI&tb!iaffbŊk_ /pc،DѣGm֤I۷o/L?^Y h׮A8tȀ-1o7srS[44k>jѢ0C۷oݭ[7!ee@/ .:NV;v,44ɓjԨ߿?𡯯o6mϟߣG-G߱cÇSRRRSS===G5ydA;G]vmLNNNKKnР[```޽ǎf16S&%%%{9}tZZݻw5޽QziaaQˣڸqY꧟~pZ8Z>z]"""<<--ѣG 4 ׯAvv-[~SN)wm޼yǏ A͚5,L.5A x+""B*Tu"ףGnݺuFy{{)޾}KZ_W<,=z%#4hY2Fؾ}޸qCY-w9!Q<6oެN6H19uoݭ[7]۷OY  #Q;v֬YZ򲴴,**JHH?뤤$e~aڴi>j8#Q<& lll*{ɞ={x عsĉK2 {{{e /a333^,;v]RTe,Y,`$Ǚ_~/{ kȑӦM4xԨQ111|Y2Xz <&T*Շ~믿޼yҲM6}]paÆ =4!DFFFHHȩSΝ;w݇5lo 20D^I Q&De`HI Q&De`HI Q&De`HI Q&@ݺuCTۻܽ{ M/C#Q柧CԒ"}a%e`HI Q&De`HI Q&De`HI Q&De`HI Q&De`HI Q&DKcdɒӧOWޡC!ڵkw->}3͛7oٲE3ϼkz5O>$00#V4B(ο5jZB|Z׭["-Z4l0->ljj~Ϟ=梺OX!!!֭B :7ԱJJJ~Ǐߺuz̙ÇQg[0 &333..cppphѢTrJ-###DfffJY2B)Kn*--}77lؐXPP#c e6OVݻw0Xh]&(((~zV KOOsT*UES/_V0vܙ'9rïÇHe///wwZ;~#HV~:[Z;P#ɓ'zf@-T(QF9"'''>>]vee'۷ ![I.\ }Yl?Z!϶) QZenn^^9s̙3 1 Ξ=kii٥K!Ԏ; !ƌSnٳgZBDEEU(#oOXoߖ  GghW<,** 5X|}}rlll1rSO=% .))IHHuڒ`cccܑ@ /`\B={{ `|R޽{+pƍ!&M$m.|ڵ"ܱcGPK/ɉ~aaaƍ=<}ƌ7LMMo"""T*r~iK g 666;;m۶...aHHȺu-6l۷W^lkoos=3VVVz? -jɓ'[c /ЧO333]z9#YzzM5kVnXIIɘ1c Q,,,`yݥΝ;BH-2M6U*u^3}tbŊ^zmBB| F[[ɓ'7ZS>|+[-Z$fϞ=e!} !^}ѣGWZ%۷5RՇܹneeK/ɏ\COFyTէNڲeKbb.OO^x_~u|.xlEDD<Ǐ/B$''oV^^^EO<):̥K̙i"''端mUóJO-[VM!ĭ[/_jժU)uA*;v3gHY2vvv~ڶnZ*j-,,pT BtYFEEj˗/K':;vl޼yY2B7^xOX*jʕF8,,瞋R/_tҲY2B+VU;1 gϾ't]vuppHLLBDEE_~eٹ !6k֬o߾mڴ)..۵kWQQb߾}={ѣBK?yBׯe˖fffׯ_?rHNN_pϨK. !;&QCXXTׯ_u?M %\~@9/˥K^^^ҪL 4q]ܱcJON:Us|!Ĉ#eIHH8xJjٲe>}Zn]XXKO+z۷om֬tܿ_1pF !ڵkWisU O>9|T vwwOOOxo-[\\\t 2Smێ?.]\\Vo߾+8|pn T 6eU*J3f̝;7%%EqeݱܹsCu V={MOOB'!ݒ%KD7mTv"N'#(**]tBM?^*kL%]?,6l+?B4h`ʕ7K]T)tqg۷CӾ}{9CR%y$]v+Wnrrr*._s .d$͛7UQ!(#xn?%z9reddDFFJ &ږ0aTujxFZ_*9r^yݥ{8ںm۶RYNvBa;wN*lٲ7]]]Ν;}ӧT{lz š4&e!@tW\ M4h˖-o߾.M'ӳgO=~Ql(nYTDѡMEaM6fIHH(S3ҢA:ufb?z<{СCR_ui֭Bܤ$!Dtts` Ν;KGFEE !弍;}zЪL^Ҩ&+-nݺCvҥ)mD7ҷo֥I^^*'qTUgQ,OhlԨGeejSO=mZYY !bcc}||juE2B.]ȉ2y 4kL#'&W +##C*TdWsz433[d+"=FFFFFFZXXo> 00~U`%?=jys!DNNNLLuN8~xWóB^ҏ8"2~)t yj7nܼyS:Ԧz+ ! [[6mhKHaBHB;VuBJ]XYYOCVvvTpss3p#>E TK=OIIjcF7j5˧OVTzWAƧyUXSXX(jaw{{.]>}ZqѩS !dzmggg1QN.\ 7EN߿ル/#!joFVۡT^poϝ;7""ɓ.\~ <:"#QǍThܸŋɓB.UC B޽=Ν;RQHpp(sرSTpikat$g󧤤dffjYwI$'tY^6cǎl /RAǠSˈ#FQRRpň)Oh~~~>>>=(b%7RGEEYXXtM㪚=˟`V$--M*8WM S ڵk)))111ҧnnn3SM62:.\fBߥK}%ܴiSHMMoc䕨jN=EZZZkn_~ڵkʅa IDATGU*ݻ tDÌ2"/^cǎ;vٳyfE 1cHl@ffUr޽ޕFDD!zY[#զzgQ) ÇKǏ_ec믣GJÇK+"ՂݻKr޼y3??_cT6ͥu$K;du'1C*DDD>>5?"`"H1ԻwN:IիWG7oTByI+[XXL8QLHHuww7ȕw8q`Z^lƍ333]7n\lYii}ҤI=/-lllut2@科/?+((HYuqqaNZɓdff.]TJ{饗_.=ל9sy慅Ik`TW_}Ufƌ54Sd޽uxU*ռyvؑ.=>}z…ׯ_~i0?sszkr8pYd-Zuj:QݳЅoTtvvB@>ZqI!D^jsU,tvZez̓olrڵ~~~{5?Kٳc-/uY{rRtR… W\m5" ~[^GV?5F @(TAڊ^Iі@SE'X؈$556Z "X`a![n]y^3 9owٷo֭i%3uԵke$7.X,yJo׿ޣI:a&"/_~WEرcWZbŊ~GࢗKR>d(CHWWWz檪B}ѭiΝI̚5k֬Y7ٙ$IP [lyWlrСb8eʔɓ'ϟ?ҥ1S_&NO&ܹsgSSS$]vY#9r$={;XYދX,nذ^{뭷>\*?/Z|Wggmvر$I֬Ypswdnƌ#{/ ^a%I_7 ¥^zٳg'8|MMoX,vtt$Iz:o?$馛&Mt[~饗^}ս{8p`ԨQ'O^x%KN:'I2iҤO|5c{{~7G8qܹs?L:/|ڵkwuꆆ|sνkkkxd_^0Є2CP.bo'I2f̘gy|2 2'E(0$8䷿mXxJ e.{mllLK.vO!B?9a„kצG>}(.6B,J{ǕwuW.dS/\XV\9o޼9 @Ʈ7|+;,XD' @A(@BBP2   !eA(@BBP2Pz޷cf=$IՍ1|w)J Q#GM]]]Gv`麽ĉhԨQÆ z H$7n\.Kmmmmmm E||رc Qޝ·#P2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BB(d=07 |lϻYL(À&i*#2AMR`r%BP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2Pz HTjllܸqmێ9R,G=}kvѢE|[ZZ~oڴbqܸqsYxg~ }=;wO>}m̙gܷT*=쳿/;;;W677777 K.]reuuKI$++BP[[[gr%SSSSWWWŁ2ITx$Ir܍7޸lٲ_|g~WF0IgWXqW&I{1Iׯ[(455ر#]_\jɓ|.K?W:/W[*{t=mڴ5k̜93rS>W_}u'xm= eM6 &,[ ,X0wt!l׿`3|+_JPHرc7n8KB5]L>=˝qlJI8p?Obm*1O(tQ,{ۦT*bE6OMMM9-F(444;vl۶-]L8|eWW׾}u9݂ EXlii98BoLsСu֝-]p _k&MO8|={/^CCʕ+y$I~_˖-2eJPػwK//[~\payǃ#Fsȑ#=c3ںu`3g<0 jkkMi D|ރ B,ƯT]_jսy&IRTzΊP&I[o6l?|ӷ[/_^BɓuL4匞~^x fϞz`92UUU_MM7I3k@Xy~@6lX#@D·STbz7ow]]]]ye{{{6lX>O3`e$IvڵjժW^y%>^vee_Wo^WGGGx=7dB?z طo7Hcƌ.\X,655?mnnniiַf͚+"ݱ|8_Ec0h2C=V2Ǐя~Ty&|>?o޼zƶmھ>#fjkkںz=ρ87C|>.::: ”)Soێ7oN 8('z(3~tXڵ.I|O믧9sԜϴ>t?Ͷo߾st=gΜ ,H{9}Ǔ'Onٲ%]_s523 z(sW\~G=crkצǛ1bĵ^[ҬYf̘{ӏInݺ$Iƌsu =Der܊+r\$mmmwO<{bX,{{w߾}wy#*w;͛|cǎ{.~vٻꪫ/'?)J]]]O=SO=s\WWW喟oϙ3;x駓$yL:5޽ɓ6-pFB$IKN0?qkkkzMX`_җ,Y{}s֭عsgWoֻ;0h21wG}tÆ 6mڱcѣGG5mڴyp \rIornkyxq]uUK,1c`H(_B믿m)S,_GTe=  !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2  IDAT  !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eo#Fz .ABF1TU3555\.af=jjj|Çg5 TzΊPf詫zv*2$r1V(* ׀p_X\ b#pV.8ݩSށ2!~W(.J QG)]]]~9LXf+w\2{ʚ/,.RGwf={A -#G,z,~ƀsS___~08qD@_B'Ovvv (b9.W2>/?~T*e89P02   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BBP2   !eA(@BwU $""*vZ>ZGƽ(:jNJ#.X>nOG;ut\)be 5$ !Yss>s o eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP dZd2xiӦ-Ydڵ;O8Çwܹc׮]n޼y֭-..ӧ9sI'5hPy|…񞪪M6-\pʔ)_y睷)S&YVVVVV͏&G/պunJ}񸶶gc_x7q%O8i@LEQUU߿e˖(rsss9CUUU{6mEѓO>yI'u)O?tɩI'tן|Q\矟?~Esy! e(|UVEQ1CQ <Ϗ7H?0L>sqn&LгgD"H$;OK/رY*e;vL2%5꫻wۄ.]\z饩q1>/Ho'.EQ9z謬(m6k֬X?!͛WQQEQǎ=ܽ䓚샰h"w>ԠO>_]vY&5۷o}֮]v 2[nMKJJұ_jkkS㣏>i%%%uuuQZk׮ YYYݺx OG"fB[[hA8m:_ILYYY<.**/^iӦ#8N;s=ݎ]~}<СC}H$'z衇}&|_IZ^D[z eYYYǀҫ]vYYûπVVXXKڂ?QEk6oޜ$G}t̙;w\bŊ+|?ǩ_ 2WSL!4^@ {k׮#<^ɴk.'ɷ~{„ '(TVV͞ R @K 2qRQQQZZEQ=Fy 'lٲe> (??Hs ??2-%P&1Q}{߻k32z;y}.]EɓCLNNNj>;v ϼ O;&7|`_'p:$ނ8ee&WҮ]Αв~Jo#ܹ .###Nޕ-oE+L&LКʤ"յk׫*Xo;#9s 6,;vy`,-//۷o߾ IަVᐓO]ẅ́V⠄2555555~&3 U~reff2555}ߩN&- e HEjĈgϞݻwO?_QQUPfiʤwݺuk`f׮]S7%%%۷od22МBe9x\TTN:թA.]-]7m?g7r4Ceee _t15ʊo3SZZZ߁ .L tr `$o|%KꛖL&-[{O?=5?~}.X 5ӧONN.z(ES)Sl߾}sf͚f͚8c(ׯ_jPVVjժ=ZhQj<`f*L4pΝ;GQ}'|j eee>lj|'+~W^=zH{d2۱/;(رСC+`߄2QvvߥرcΝud2vڷznۼysE]w]"M$#GL.\cm۶-YYYϿ曩.,77*^@0x?NEW~(ٹsg<'H5*v2)}K_}(f̘wqDbʕi ~F(EQH$^{63)**=ztz_/ܹsɒ%鯞W_}u}hh~Bя~4dȐӧ/X`Æ v?`>'%K.d_UZZaÆ޽{;ѣGs~!P8G9r8k׮^{A_EFK/P eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP eP d;KhGlh%F A A A A Ajpy HO"ǙLhK\4'?R9v4fL&[z 4PSPPKط^D ]ǀҫ&777+x*[z 2Zo&-]{-[nw:"[h)h ?}4ܦڦS̡gƍ-}kM/ -MSwڵe˖]p***L++++**Zv=ҩS?IEEEMḾI mπtEEEwق롍:!A@Sk]LUU… .]tիWo߾uԩSo+ ;wҥKW^]XXxQG 8d?ieee{袋꛶f͚9s[nӦM%%%?ꨣ媫gϞ|uuܹ[n ٿm^2VzᇟבvGQ\\\\\|'7nڴiƍ7n/?9s|'vcƌ뮻;Sk׮r?y8LFQs{gYrě!C7Ϯl={Ϣ(1bԩS(Zfͭ:yԄ?P&LKO<ܹsgy17h)++:tK/tM7oUW]OOq}ݫ/^]soرq%3hРgyfڵo](t IDATرco5P'??3ϼۦNv_WC IT^^7oJڄM6 :tLmAv1lذ+˗/Co3XhQE%%%^~EM<.Ko1~vOj\RR2hРw 555+FQԫW'xb…V*--}jժ#FTWWy?K.Imfff^s5ҥK,Yomŋ_s53BH=y /HDQty督Gn߾}^.eǎO?#/n`@~xS_/Aʏ^M6rwygǯ[.K/ .`wvIx|M75|tMw}wjs_}j\]]=ux歷G~i(@ks)r) я~oΛ7w^}/%9sě6̟??Lƥթq~=؆sYgva @pؘi ,؏XbÆcǎ'|>/ڽ{!6mZlYjܜtIiL -SVVVvС =ĉWXKv 70vؒ&^&@TTTԘix˖-Mرc}/'fiӦxg#C]6@ KK.;vl=rss o۶-}ZuuE]4z=+(n:q^z;͵p6%''1ڵko߾gK?}[]TPPnݚuBhP&LN0W^/,YR[[Eі-[ϟmp gNͬ{fOiӦ ._n9Π>qEaJHeee#J;W^ݘYWL̘1c;wՍ76w]EԩS_;ӾovW^9w&Z3@[Ȃ,YҟʴyF>3~JTV\٘4re^xᅧz9UUU\s͖-[xg.XgOۓdS--Zpac͛7/{qΝ;ŋ7w?N:]vw6YbEV C'{ _>裏}A\rРAK.MmN0a֬Y L<3fϞ=~l3g,--m-wرiN<8p~\[nMe6nܸlٲ}RVV&??gϞgϙ7o^mmmٰac@믿_ƛ>|pW8p^{3xԫ|D"gd7nذaM5۷o|w}7ތoddd?E(zWq߾}SSO=05^vi>kϘM2MC3I$?:W^y^+:tG.//d29f̘fn I*++\UUOǛqVVW\ou] t0>-hÚovaG7'N裏M858}NϞ=njo>]vnÅ+.W^y%8Љ(++kh7bرcNNN} mۖl߾}çMBr)ӟ(裏N;SO=5܏?4}f^^o~}7u%K6㎷zkу ԩӆ f͚SO͚5+>{N>}zjQk'O4hЉ'L&,Y2{?"s}衇R3Kچ&eguܹ%%%q(@ӹ{~?sjO?O[oqxvM2sYn]j̙3gΜY)S ӦM>|ER{f̘1cƌiԩSx5WM>1cdffu¹;>/w 5eh222n馋/^2eׯ__PPpQG 4?СCD}O4">UcأGEM4'XtN<1cƌ5*;;S>7|/;,_cӧϏaÆaÆ]6f@&בG9vرc~o岳njs-,^xΜ9k׮ݼysQQёGyg|k_k I'4~7!L"޽~,hc24D"ѻw޽{OcǎxYY wUUէ~wqyyyTphc>â:⾏.M@ 4A@Q%bKn 'c7[1vQ&{D$T yq{/H;ϋ\snPܟ3s;wNj_py >|p:yqJ<6mnYFR42&&f̙>}meJ 2aJ~3nܸׯ_gѣ/2 @lذa-J%G/JOO%KHk׮ݺuԩSfʹǏiiiMM 6hhhW52>QF.G>M?w%]o9 ݳgcqU+LJJ88#mm۷7o|o߾edN.\HJ@F(M444Ə?lذ{8qƍ˗RU6m:uT^=+PO¢E-Z$wF__Ȑ!C IeϢ~QQ?]eZԏ>H)w@q (OBܺukԨQrWN栌ڵkX$2[ #G888x{{zU({dʄj*(((S"""ӥKϟ]a(cd!BCC[j֭]={2Uq(+4.@!BBBZjuܹjժ4GtRN I&yyyyP%$$]E!P*zzzrWT9(ӠA7o !E1 [dIjjj _~W.Z*J맙rWQ,G/8qYjn:<<<Ӏz-X cJ|+Vt)AJ*8qBw hժUDDŋn׮ӧO3N޽Ç[ *@$sPFaddtIGGG߿u֫W]m2477믿8`ii)G(!N:U^=ǏVP(&LxaϞ=e[!*W|ԩuft+WVX @PR2B*U:u!cŋ]֨Q#@P2BccSNթSG)cI(JVPFabbrڵkK+VT*U+qAY{{{{ƌdePE~ѢE7]v?ڋ/vY> E1cFiӦn999@JK@#(OBSԏ000(G+L~q> eI(LHHHQ?ȃ2j՚8qbdddQ?(oVZhRSS'11c?^UǏ/Si@RA+VX[[Ϙ1#::'yij֬믿&''CPyPfΜ9-޽[DRToߞ2eՒ%K̙SDجXb޼y{ܵfQ?˫cƌ9{w~nݺ ߿j )>>>۶m{𡺳uk֬+G>B+]ZtiXXwޕ+WxV LEBٝ>}z˖-RӧO>}z[lٸqƍWR壖z+WΞ={Ō*W=x`BQ_ "wyUdTA!B2dH.]/_~/^HRʪqNNNUT122T_Jk/_}իW>d'NTR|i()(#122駟fϞgϞUV]r%gϞ={lΝ[uڅQ,ʔb Httt 4hРk׮[ѣ^ܼCcƌqqq)"eOdd3g”Ji}э7*WlkkTbł/[ T*U``ӧO>}TfMkkڵkkj'Rg7l? }իy۰a)@.^zշo_ss|wSL߿yǎ=zuBP(^^^/_.oذA߲e:u |(iJݻ7ۻ?xteAJ܅ʎJJ4hРK.+W ٿӧOIII={rJ fddٳ߾}[NwwF%''_tiʕB?[nݺu+`͛75kbŊqqqBʕ+ !… )SS~լYSRoݺUܹs΃ *`@R2w*uII .\`9s#FqF7P?~bbb7lؠ'ucС...BÇ<(Ӳe˖-[ !6m$e&Nhoo~ݫW/mmm]///WW@!Į]ʠa$@7o޼QFS2BMM~aʔ)۷Ϝ9o߮NHj׮^͛.ݿ_}\ڵk3dFFFgϖڷn*"Ǝ22RJ&L֌3֭[{!֭[۴ieΝ1yִiS9BTT)뀎;R;--MCC;ʸ1cƔ/_>[FFFR/k/_s211 SZFRRҪU066Hɠ!((5jf͚I"744ܴiw}W ehhhر^zҥJz_llvgϞeGK_rEXϟ2eBPGFF/Vrʅ o}Ҕ۷2dH=PhhhH R9s^zmܸŋʕVZ.]_rӻufaa!puul2!}N677|gnݺuk֭w TRZ_'$$Hsmll2͝8q냂ttt͍rv̙1ZZZJ?|n/.Pj)cd{B!(__ݢEl|իWraΕE".eM tttvjjjLLz0oK+۔S(NCCP}ݻdAď@YX5~.w m"b?%"jjO<"5%"(2|{{{WW5kּ~ZPF߾⋬W\7ni^8( 2G>.\XnLwSRR߳gOSS_zURR'JqRjզO~޽;wL:2ӀիW7n~ϟ?N^%"(xgώ5 YfըQu֛6mN:%+(#Q*nnnׯܿ޽utt29s̰aLLL t4YJ@iQ2j:::=zسgOTTƍ۴iP(2HHHؾ}{---Nz=J@ W2j}ٰaN<mmmi@DDҥK4h|hY@U:2}9ӧO>}֭P( ̝;]lٙ3gN7~7Q:Jy޽{{X[[K'''u>&#MMͮ]v:oNP2e>|(cݻ+++)m>&3f,[۷BGZ(d888tZjR>%5mmmsss)(Z*P,,,ӸqǨT0K1331J3Fjm۶ԓ9(Sj޽{ӧYfǨikk/ZV2@[[[5[* F~'2M͒rEذan߾ d,eA9rDj@QlSSSuիW2V2Oe\\\m---2,!!!--M* Rӓ AGG^z_Bݻw8Pz ST.B)KPZy_?Cdd9(cffvY{{{!DPPP֭_.oI(d!,,,_7!=z԰aî][y.MSCݮZtÇ>Q:tK.\2|"?z (2(cggW(:(d<~X%|@PM ȞJzYxxxLL۷ouuu Tbgg%wu(}JVP&66g߾}׮]{M 6ҥÍBR%ٳgzxx?~<۔"!!SNS2cǎӧB4>44t׮]V z"##{uMMMC?(d>ziׯ_W_~O<9sM֔bʔ)=6m޽{ׯ/rPjYj߯XB__ʕ+hѢ {V\Y$>IǏW( ˫%=t͛7W('O,YXXH/Ǐsn_߲AΠLhh͛7vᇏ>mڴf͚I'OVRJP **˗[nZt?S^,eACCCu˗X!Em@;v,11M6*Tuܹ+WHYfݻ?W(Bʕ+4ѣGuԑ,Y$a;( ʨSTB__|qI!>ݻw"j*?J mۦT*҉T(9>|ViԨn:--OOOO_zյ0!IIIgΜy-,,ZliffV(+9s& ݻwUV/3=ңk׮P(Οɓ'5jׯ_[**00ӧO>MJJYTfnÇ !u퀴;wܽ{իWBKKjժ988TXƞ9s殮666yJ 2W~tkrvv[ݻw/_ѣG7n \S^^7oޜ;w.444>>IJ|j XXXH̜9sɒ%YV9Yxŋ}Q (/^/Ĩ;544j* >,OOOooo!Ĝ9s˗/4i9rɓ###3>񫯾ڸqcŊU*Mیv|5kKȩXhь3[n4h˗ 3!DfAJua//7ofZVZsӧON __hWWWSSL޾}lٲ_5:::ӭˏ5jҤI.=sM6%%%eo֬ٺu֭W|BCC...,e^|0IlG>w\ƹg7nNM6&OӞ={&''cqӧO ! Ҷm[cc7o.^͛7B???޽{Bnݺuڵf͚_dIXX" `ٲe%#66O>R*\r&&&vvvҭ ݻWjׯf͚*֭RcΝ;w4hPeU*Ձ=ztoyԶٳJ/x1c.\qbtttVåK333wwwkk똘SN;w.99]Y)|19"HLLT!/rADFFΞ=۷uqwwoԨQrrKV\)ŭnݺe:ɓ_}jjjvٹRJ7n8q;~_~뫥U:K2Jr-ZP ԩcdd͛G~: UV믿r? Z~eB̙3А.OiӦ#G^r%>}ZWWw޽:uzڶm۷o_x!Ynѣ}"Zn=xzIYgP槟~7o^_~Ej'Y<^^^B]ve ܻw/88>c+W=mڴ dܷoߜΫ)VJ\rB\2**Jջw'&&Æ zzzRg=">1(ۡCJ)-[4h@}ݻwǏߺuիk֬Y*|ԩSwС]v:t7kJɓ666U,tHMM?믽)!B6l̙3 ^ԨQ#(C xiӤzann_g>s֮]1%#022={ԾuVesNF}3dJr޼y+WB߾}[}+44t۶mR}ժUꤋK.7nk,܌rzb޽ëUQӳ}vuJFRv)SHLf_^c8q"cJFQb-[|W9s>!^:w܊+qԩSo߾PJ'N ! EN &rN'OIPGbbb|[pa牢NJر{yye=Bݻgꏎ^z3F EݺuW[n"i2ƌk׮ s3]||IӅNNN-r1wlMJo'Jn:h"SSl\b۷곢ʼBhii}6lԩа]vV _xqK;vvq߾}~z K ++\3]]>}dUHJJZjU#OwMccƍg5k֬sTқ7ov^pAj6ۉJ2۔RAfkJsN{{˗K=vvvǎ300"(_|Νebb3888((HjUjAS?#F1bJzydddLLLlll LLLMHѵkפs.~!!C>.O^dɒlo1cǎ:]\\MTZY:ViҤIǎ9rdv*TdgL.׬YsΝw^|||֑*J} S͚5sYz87^L̙-$pppXbE6m2=rry fI)!T*ҥKݻ'XtiNqI"##O:uڵ4###''6mڨwann0 b)G~ cOOO'--ڵk׮][lYug 9yڵk?"RSSvq+ 877l0F,fffs:tnzzz5>3rGPBqA)%;J۷;ۏ=ZKK(+45\4zR>>nv8pܹs ҭ;v_W>|z?ڽ{re]0--m[lo``PNzu}ѢEϟxWGGGTJHKK{}a䃻mܸqԨQҳg̘1uԏZjZ˔pO (gϞe?6[[nݻwR[[[T&&&Jǎ>}zQ٪TtMHHH.Þ?^\7n8/]$HLL3fLF֭+ >pG.5c g+V:th-\]]ԇy{{gP( _~- rss˩԰YpGٵk׈#vÆ 7mTN|V զMd)Aȍ7޿ѣG_>Vؾ}{ doooLw:%SVQFI'4l޼B+W;vSNX! <B2,88 *U4iҤIiӦ]pk׮o߾MIIYf͚5kIIIGUVI:l߾RJy|tڵ}}}O}ZEDΝ^vmNcq4KL R?~wR#22r )ܹy{\ooo--S*U_HE4… +VطoѣGs>rR&M_OOc#W拍]|BCCcSLeԨ\roCCzݺuKܮ]ª [[Ν;9rD?j!pOOO+A4hc!ıc>|XNL޿/dR IDAT Bԭ[W.m?ѭ[l466o޼6l߸q߾}[1{lWWW>1zkudzmmmR2j֬Ą .\ زeKGi@DDİaävϞ=DȹLpp;wԗիW߾}{hhh\\ܫԾ}B)IRY&::Z1pYoܸ!5\\\ Ec\\\Ɲ;w (@N/_.}WWׅ >}4)))<<| 4kkkZlz%RIIIGiժ})Zqڵggիg :{lW0aݻwBXf|\\\-O~/^رŋBSSL+dn^JVZ}+Wǃ jӦ=zСCݻ'&$$l߾iӦvJZZZTbLΠmccs8)gΜSN^r.i6l(5"## RlٲE:$..n̙666ʕ377[f4XOOObeceeIzzzZXX/_Դ\r]tvtwڴi-ںARW^+V w޶m۾'%%/_^'%%IM4YlNNN^xqzLLL 9r{Gdc,J-[9͛7;::VPLOOoРAҭիW;99Vh3(#$DEEoB]]I&)xq"""14DWH>W^ǏzEΝS [ ϟ2eJ]-3QjՕ+W.\P4?eէ&G?|'tK@nZl{8p 00PT֬Yݺu|4,nݺYXX!\]]3Ig8{{{iq*W, r$͜9SEE6m9884F :t yU˖-xΝ;ܹȑ#qqqUVmذåj/^wٳg Almmmmm۶m;dԭO_B d[}=zHѤI֭[eJbbv8˗2d+""B*#'ZZZm_eUKPѧ[R,_,?eU.㿝 w%O&(Pb 8pYoߢE-Zd˳jԨ1q\4@[[[[[;kNEÆ 6lu]tժUKReA/>|_PXZZvA066{ZZ-[fZRJcǎ;vld dn__لUT&psssss{eԮ][j>}FJw!0007n\wXB] 2B! O>*JXk}R{dY>qJݨQjժIǏUFRRo+VljR'թakkrΝgϞQ!/R#1cY9887٪VZRRRkBƷ :MMMl**|qMZcI.]ZZwKfEPdg>%%%==]zPFc P6?T*N,455ve!D>}/_>p@I^>>>ƍ.ndd$[̇9Gy]wX\~B 63>>>==]q{8Q\۷o߾}sի)S.@5*TP{ E!ʦR[FeSRR Ng@*lQhhhd $$$%P1(JşL>Q dpǏGFF :tڴiWglll/^,oG/ ! ݻ۵k'xA ƏTb(`ժUBR9y+K߿e:(C… mڴ.N>s7nS2;v300LGezzz+VpvvNLLLKK[zիJRPqv9O§鞞m}}}TSTL)fccsI??>{˗nnnrٳg3ٴųL&JR322,a-,,>BM6mT*O栌ejiӦ\Sjvvv|RP#Fv7nH '''mm 3(sΝ۷o/ׯxf͚XGiذ_% ,--3 HLLT7.2>ݻv\Ү]RBԩSVj**Ӏm۶ ! ZlY@MΠLxxbŊx,B>[nϟUr$9rdŊ ֯_Ν;;::ZZZ*<.Uu@ܲ,l^ 2_~066 BܹsΝΡCtR@)N /:uJػ(nϙd RQ(QЂ/54JdFMJVK@F$**EPY+ AE`f{:/ lw}~5k9D^ @}HyE^zuZlY+J9([o@$늊yyyM4I rPfόfiwQ ~;|{-G (@ǭ/^f͚W_ݵk״ve***gyfeeeU3 lڴO>ѣ:L&Ra,Xлwn)=\__s~!G"(SZZz9,^o~饥u IA?f;{r^^^^saÆ=(G2eee޵kW2'?ٰaܹs}ѽifշrKƍ믿>8'u6m^{xUV5rqMUVu @[/tIk׮>}o` 6TP\\ܳg>} 4o߾L&V8FADn[o5s/r͍7nݺuͅc88]PFݻwϛ7oʕ[l)))9s?v9wիW'tR}UV^z;wv%xAAfҺY88uPI~5kq}<3~ȑ#z½;nܸ#<2f̘iӦ?]~}ճ{El0aW_}Uue]vvf/ĉ-Zǡ]!C򒑵k{IlٲO>kڵ}_|EaԩÇ?LnE^ @ʆ۶mi+WLR2!뮻n 'N1b¬Y P^^>v{GB?%\cǎh|Ȑ!_~)Ç92С9眓ԥٳL-⊽'rpe]Ν:묤5k־͘1#):utyqtڴiwygaO=Ԝ9s&MԺu zoo!/GyWLҡCdʕ+'O|u]3gLۏ7n-[&ӧO:uj\0L^NaȐ!7>Lna{챥K~k֬9+<_|q7@$ o{½L>=)F(gܹ79s楗^\xC޽C^ᡇ;vl& !F:S֮]B?~ԁ۹s˿$MVTT;:qij:kժU!3f?LƯ꪿ۿ\l|pI'q͛7?}SY8t(3cƌ.]~ӦM{w>?(iG!C$y/r޼y{OXte˒HE.88nѣGx%Zn=a„iK.mVMɄڶm{w$ŋs%%%Kj4U͚5kΝ!?o߾վu,21b_nD}ݔ͎]߿.]дiӟ{#W{BϞ=b߰PVV5jӦ #<#'Nȍ׼Rnߥkj%'CKlvܸq{7idjVWp 6w|0???w(]k=SNiԨڵKVZuܹ k׮Isr3f'guŸ?O={<)?TVV&uee3K}޽~5jԹsΝ;oܸq W/...++ !=,27t)7i]+*****:$ IDATyO?Oaqw-0UV5O8w~ܹ=B8 PfᠥywyN;[ k>hR1UvH3(dɒ\}i/odE+V3gNR׼4y)ur)SdTVV.Zhƍ .>|x6 !NK5[i(Kd238#N zc;d2&e:tM6-..N٤I.:fP3Lm۶X"N LK.i޼y֭&LH)intq]pJaݺuKD~~ٳR2!ᄏ(pw,[,fhR!l߾/?~PRb̘1-Z=zG}ԯ_aÆ}?S;vd"M6-,,>8ڵOBӧO>}7??pZn$+nD"/>L^j:-[Py뭷mHz (APvԇߍܑv /_[H Q 2DAP(A (@e Q 2DAP(A (@e Q 2DAP(A (@e Q 2DAP(A (@e Q 2D ы/KNl<[eE (@e Q 2DAP(A (@e Q 2DAP(A (@e Q 2DAP(A (@e Q 2DAP(A (@e Q 2DAP(APv|cL&xyQpd2,pj P+'x⭷ !/y/z1LXt+zȐ!ww 'd2B-cǎɄ?7oΝf}Ѥܹnݺe2L&өSo3LN:uwWe‹/;w1bDiӦzk2k׮7|3wh}QRMB7tSAAAa˖-z5 VJ;// ]tԩSR/_<7`8ꨣкuSN9eԿ؃26mJN8]tI*7o'gR4CIb؃2_|EeeeRk׮۷oOm&ݻ׭[Թ4zׯ?Ć88i7mΜ93 5m׮]~aRw!)>ӊ=o}+///Ycǎ9HAL&STTi/͛C}M?܄f͚͛7O6lzJ̙|& 8p ԑM MA6g GFQQс|o s=ܹѣsGhܸq~~~ i޼yR7(@^6}M6%#:t;k׮o57AP -2Xr?|%\rumۓ-ZaB&Ml;AԺL&S1@fS#A;"nh<ZQ_a:39; !(ٵkԩS}'ٷnG{OnԨQRl߾2//o_ݶm[Rmvm<'y u?O͛>Rw޽yt!:*:qDZrQ*+++//?):"&BtDfR+_k2?2eڵkmڴ9r\Lfʚ7? 2ݤ :"(?O)((ܫo}+Woݺu_Al6 T=$(B}ݗ]v[:v߳ڷoWYYBX~1S/"=ZjoMq?:묻@R2!ŋkڢE},IP&L6mǎ!.]L0իWR[o'E=Eev1{Nk׮Y;I~:@]v 2￿SڴiSRR'|__X"裏Wd2U'?S۷o!jժ?(̧~w.nHL&3jԨ_!Es=cǎmѢE믿~g{da5jT7=(aÆCB=:cƌ|N:e2O>dǎɜ0` !=(~CȈU{ĦևR4bp5;V]A)(EEֵܸ+*܈xFq%E-bMb&3s0iT3ɜ|^o:'o˜;sN55uZwC=ztbb2[h||ԩSEO=PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  P}E=-?Y@"(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DƊ֪El؂g3Z ڵ)n9 T9-l&ͤV=PuSut> кa 6`KtfR:7]vnm[ڻڧ+ޖll+瀰Suf to&Nagw&z}tt)5L+%Ia-|L\!+ޖlI(ST*J믳N-ھ8 +ޙeBO@;e  PB"e  PBj6OIDAT"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  P}Es}ᇟ?PV;99ci,gϞx຃h?LK.^X>|\.Ç7_~eRid;歮~wuё#Gj:77׎PfjXu]o߾=_zpb?cs=22arytt~Kno駟68`ddd(`=L$Elme3"ټzPl#Y%75==} xx㍿3f1,z`޽f.g'w瀰Sl[7(pnyKKK?7::X2`tubxxx#2?EߢG s@`K8@6e6o``eX{"@Q| 6ZgڵkƯK/=000/Ia[ vm͇k^/pKڵٞVՅbݻofڳgO/@rcܼ'5_{7^vR8Х\3;)5歽1::ޑP7i+>ڀjڇjթ kz^V ^k7Zf3a'_&%l&: ­6o߾}azʬI(yo~z͟17l^__xc=33a.]j,ߎP%=Pcq…xbc199900ЎP%Gi,fgg^z_|Ec=55վwBӧu9sfqqT*=m&LK3O8P.\8Gy'  Pf 8qbpp̙3Zmeek=vɓ'rQPlr|񩩩j{:tѣEPf댏:u)vA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2D+z[jJR@[]]W[V^ZlJR. l&: \׋[/A(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2D;(+ ?IENDB`addr2line-0.10.0/rustfmt.toml010066400017500001750000000000241332105314100142450ustar0000000000000000fn_call_width = 100 addr2line-0.10.0/src/lib.rs010066400017500001750000000555011346220724300135730ustar0000000000000000//! This crate provides a cross-platform library and binary for translating addresses into //! function names, file names and line numbers. Given an address in an executable or an //! offset in a section of a relocatable object, it uses the debugging information to //! figure out which file name and line number are associated with it. //! //! When used as a library, files must first be loaded using the //! [`object`](https://github.com/gimli-rs/object) crate. //! A context can then be created with [`Context::new`](./struct.Context.html#method.new). //! The context caches some of the parsed information so that multiple lookups are //! efficient. //! Location information is obtained with //! [`Context::find_location`](./struct.Context.html#method.find_location). //! Function information is obtained with //! [`Context::find_frames`](./struct.Context.html#method.find_frames), which returns //! a frame for each inline function. Each frame contains both name and location. //! //! The crate has an example CLI wrapper around the library which provides some of //! the functionality of the `addr2line` command line tool distributed with [GNU //! binutils](https://www.gnu.org/software/binutils/). //! //! Currently this library only provides information from the DWARF debugging information, //! which is parsed using [`gimli`](https://github.com/gimli-rs/gimli). The example CLI //! wrapper also uses symbol table information provided by the `object` crate. #![deny(missing_docs)] #![no_std] #![cfg_attr(not(feature = "std"), feature(alloc))] #[cfg(feature = "std")] #[macro_use] extern crate std; #[cfg(not(feature = "std"))] extern crate alloc; #[cfg(not(feature = "std"))] extern crate core as std; #[cfg(feature = "cpp_demangle")] extern crate cpp_demangle; pub extern crate fallible_iterator; pub extern crate gimli; extern crate intervaltree; extern crate lazycell; #[cfg(feature = "object")] pub extern crate object; #[cfg(feature = "rustc-demangle")] extern crate rustc_demangle; extern crate smallvec; #[cfg(feature = "std")] mod alloc { pub use std::{borrow, rc, string, vec}; } use alloc::borrow::Cow; #[cfg(feature = "object")] use alloc::rc::Rc; use alloc::string::{String, ToString}; use alloc::vec::Vec; use std::cmp::Ordering; use std::u64; use fallible_iterator::FallibleIterator; use intervaltree::{Element, IntervalTree}; use lazycell::LazyCell; use smallvec::SmallVec; struct Func { entry_off: gimli::UnitOffset, depth: isize, } struct Lines { lnp: gimli::CompleteLineProgram, sequences: Vec>, } struct ResUnit where R: gimli::Reader, { dw_unit: gimli::Unit, lang: Option, lines: LazyCell, Error>>, funcs: LazyCell>, Error>>, } /// The state necessary to perform address to line translation. /// /// Constructing a `Context` is somewhat costly, so users should aim to reuse `Context`s /// when performing lookups for many addresses in the same executable. pub struct Context> where R: gimli::Reader, { unit_ranges: Vec<(gimli::Range, usize)>, units: Vec>, sections: gimli::Dwarf, } impl Context> { /// Construct a new `Context`. /// /// The resulting `Context` uses `gimli::EndianRcSlice`. /// This means it is not thread safe, has no lifetime constraints (since it copies /// the input data), and works for any endianity. /// /// Performance sensitive applications may want to use `Context::from_sections` /// with a more specialised `gimli::Reader` implementation. #[cfg(feature = "object")] pub fn new<'data, 'file, O: object::Object<'data, 'file>>( file: &'file O, ) -> Result { let endian = if file.is_little_endian() { gimli::RunTimeEndian::Little } else { gimli::RunTimeEndian::Big }; fn load_section<'data, 'file, O, S, Endian>(file: &'file O, endian: Endian) -> S where O: object::Object<'data, 'file>, S: gimli::Section>, Endian: gimli::Endianity, { let data = file.section_data_by_name(S::section_name()).unwrap_or(Cow::Borrowed(&[])); S::from(gimli::EndianRcSlice::new(Rc::from(&*data), endian)) } let debug_abbrev: gimli::DebugAbbrev<_> = load_section(file, endian); let debug_addr: gimli::DebugAddr<_> = load_section(file, endian); let debug_info: gimli::DebugInfo<_> = load_section(file, endian); let debug_line: gimli::DebugLine<_> = load_section(file, endian); let debug_line_str: gimli::DebugLineStr<_> = load_section(file, endian); let debug_ranges: gimli::DebugRanges<_> = load_section(file, endian); let debug_rnglists: gimli::DebugRngLists<_> = load_section(file, endian); let debug_str: gimli::DebugStr<_> = load_section(file, endian); let debug_str_offsets: gimli::DebugStrOffsets<_> = load_section(file, endian); let default_section = gimli::EndianRcSlice::new(Rc::from(&[][..]), endian); Context::from_sections( debug_abbrev, debug_addr, debug_info, debug_line, debug_line_str, debug_ranges, debug_rnglists, debug_str, debug_str_offsets, default_section, ) } } impl Context { /// Construct a new `Context` from DWARF sections. pub fn from_sections( debug_abbrev: gimli::DebugAbbrev, debug_addr: gimli::DebugAddr, debug_info: gimli::DebugInfo, debug_line: gimli::DebugLine, debug_line_str: gimli::DebugLineStr, debug_ranges: gimli::DebugRanges, debug_rnglists: gimli::DebugRngLists, debug_str: gimli::DebugStr, debug_str_offsets: gimli::DebugStrOffsets, default_section: R, ) -> Result { let sections = gimli::Dwarf { debug_abbrev, debug_addr, debug_info, debug_line, debug_line_str, debug_str, debug_str_offsets, debug_str_sup: default_section.clone().into(), debug_types: default_section.clone().into(), locations: gimli::LocationLists::new(default_section.clone().into(), default_section.clone().into()), ranges: gimli::RangeLists::new(debug_ranges, debug_rnglists), }; let mut unit_ranges = Vec::new(); let mut res_units = Vec::new(); let mut units = sections.units(); while let Some(header) = units.next()? { let unit_id = res_units.len(); let dw_unit = sections.unit(header)?; let lang; { let mut cursor = dw_unit.entries(); let unit = match cursor.next_dfs()? { Some((_, unit)) if unit.tag() == gimli::DW_TAG_compile_unit => unit, _ => continue, // wtf? }; lang = match unit.attr_value(gimli::DW_AT_language)? { Some(gimli::AttributeValue::Language(lang)) => Some(lang), _ => None, }; let mut ranges = sections.unit_ranges(&dw_unit)?; while let Some(range) = ranges.next()? { if range.begin == range.end { continue; } unit_ranges.push((range, unit_id)); } } res_units.push(ResUnit { dw_unit, lang, lines: LazyCell::new(), funcs: LazyCell::new(), }); } unit_ranges.sort_by_key(|x| x.0.begin); // Ranges need to be disjoint so that we can binary search, but weak symbols can // cause overlap. In this case, we don't care which unit is used, so ignore the // beginning of the subseqent range to avoid overlap. let mut prev_end = 0; for range in &mut unit_ranges { if range.0.begin < prev_end { range.0.begin = prev_end; } if range.0.end < prev_end { range.0.end = prev_end; } else { prev_end = range.0.end; } } debug_assert!(unit_ranges.windows(2).all(|w| w[0].0.end <= w[1].0.begin)); Ok(Context { units: res_units, unit_ranges, sections, }) } } impl ResUnit where R: gimli::Reader, { fn parse_lines(&self) -> Result>, Error> { let ilnp = match self.dw_unit.line_program { Some(ref ilnp) => ilnp, None => return Ok(None), }; self.lines .borrow_with(|| { let (lnp, mut sequences) = ilnp.clone().sequences()?; sequences.retain(|x| x.start != 0); sequences.sort_by_key(|x| x.start); Ok(Lines { lnp, sequences }) }) .as_ref() .map(Some) .map_err(Error::clone) } fn parse_functions( &self, sections: &gimli::Dwarf, ) -> Result<&IntervalTree>, Error> { self.funcs .borrow_with(|| { let mut results = Vec::new(); let mut depth = 0; let mut cursor = self.dw_unit.entries(); while let Some((d, entry)) = cursor.next_dfs()? { depth += d; match entry.tag() { gimli::DW_TAG_subprogram | gimli::DW_TAG_inlined_subroutine => { let mut ranges = sections.die_ranges( &self.dw_unit, entry, )?; while let Some(range) = ranges.next()? { // Ignore invalid DWARF so that a query of 0 does not give // a long list of matches. // TODO: don't ignore if there is a section at this address if range.begin == 0 { continue; } results.push(Element { range: range.begin..range.end, value: Func { entry_off: entry.offset(), depth, }, }); } } _ => (), } } let tree: IntervalTree<_, _> = results.into_iter().collect(); Ok(tree) }) .as_ref() .map_err(Error::clone) } } /// An iterator over function frames. pub struct FrameIter<'ctx, R> where R: gimli::Reader + 'ctx, { unit_id: usize, units: &'ctx Vec>, sections: &'ctx gimli::Dwarf, funcs: smallvec::IntoIter<[&'ctx Func; 16]>, next: Option, } /// A function frame. pub struct Frame { /// The name of the function. pub function: Option>, /// The source location corresponding to this frame. pub location: Option, } /// A function name. pub struct FunctionName { name: R, /// The language of the compilation unit containing this function. pub language: Option, } impl FunctionName { /// The raw name of this function before demangling. pub fn raw_name(&self) -> Result, Error> { self.name.to_string_lossy() } /// The name of this function after demangling (if applicable). pub fn demangle(&self) -> Result, Error> { self.raw_name().map(|x| demangle_auto(x, self.language)) } } /// Demangle a symbol name using the demangling scheme for the given language. /// /// Returns `None` if demangling failed or is not required. #[allow(unused_variables)] pub fn demangle(name: &str, language: gimli::DwLang) -> Option { match language { #[cfg(feature = "rustc-demangle")] gimli::DW_LANG_Rust => rustc_demangle::try_demangle(name) .ok() .as_ref() .map(|x| format!("{:#}", x)), #[cfg(feature = "cpp_demangle")] gimli::DW_LANG_C_plus_plus | gimli::DW_LANG_C_plus_plus_03 | gimli::DW_LANG_C_plus_plus_11 | gimli::DW_LANG_C_plus_plus_14 => cpp_demangle::Symbol::new(name) .ok() .and_then(|x| x.demangle(&Default::default()).ok()), _ => None, } } /// Apply 'best effort' demangling of a symbol name. /// /// If `language` is given, then only the demangling scheme for that language /// is used. /// /// If `language` is `None`, then heuristics are used to determine how to /// demangle the name. Currently, these heuristics are very basic. /// /// If demangling fails or is not required, then `name` is returned unchanged. pub fn demangle_auto(name: Cow, language: Option) -> Cow { match language { Some(language) => demangle(name.as_ref(), language), None => demangle(name.as_ref(), gimli::DW_LANG_Rust) .or_else(|| demangle(name.as_ref(), gimli::DW_LANG_C_plus_plus)), }.map(Cow::from).unwrap_or(name) } /// A source location. pub struct Location { /// The file name. pub file: Option, /// The line number. pub line: Option, /// The column number. pub column: Option, } impl Context where R: gimli::Reader, { fn find_unit(&self, probe: u64) -> Option { let idx = self.unit_ranges.binary_search_by(|r| { if probe < r.0.begin { Ordering::Greater } else if probe >= r.0.end { Ordering::Less } else { Ordering::Equal } }); let idx = match idx { Ok(x) => x, Err(_) => return None, }; let (_, unit_id) = self.unit_ranges[idx]; Some(unit_id) } /// Find the source file and line corresponding to the given virtual memory address. pub fn find_location(&self, probe: u64) -> Result, Error> { match self.find_unit(probe) { Some(unit_id) => self.units[unit_id].find_location(probe, &self.sections), None => Ok(None), } } /// Return an iterator for the function frames corresponding to the given virtual /// memory address. /// /// If the probe address is not for an inline function then only one frame is /// returned. /// /// If the probe address is for an inline function then the first frame corresponds /// to the innermost inline function. Subsequent frames contain the caller and call /// location, until an non-inline caller is reached. pub fn find_frames(&self, probe: u64) -> Result, Error> { let (unit_id, loc, funcs) = match self.find_unit(probe) { Some(unit_id) => { let unit = &self.units[unit_id]; let loc = unit.find_location(probe, &self.sections)?; let funcs = unit.parse_functions(&self.sections)?; let mut res: SmallVec<[_; 16]> = funcs.query_point(probe).map(|x| &x.value).collect(); res.sort_by_key(|x| -x.depth); (unit_id, loc, res) } None => (0, None, SmallVec::new()), }; Ok(FrameIter { unit_id, units: &self.units, sections: &self.sections, funcs: funcs.into_iter(), next: loc, }) } } impl ResUnit where R: gimli::Reader, { fn find_location( &self, probe: u64, sections: &gimli::Dwarf, ) -> Result, Error> { let lines = match self.parse_lines()? { Some(lines) => lines, None => return Ok(None), }; let idx = lines.sequences.binary_search_by(|ln| { if probe < ln.start { Ordering::Greater } else if probe >= ln.end { Ordering::Less } else { Ordering::Equal } }); let idx = match idx { Ok(x) => x, Err(_) => return Ok(None), }; let ln = &lines.sequences[idx]; let mut sm = lines.lnp.resume_from(ln); let mut file = None; let mut line = None; let mut column = None; while let Some((_, row)) = sm.next_row()? { if row.address() > probe { break; } file = row.file(lines.lnp.header()); line = row.line(); column = match row.column() { gimli::ColumnType::LeftEdge => None, gimli::ColumnType::Column(x) => Some(x), }; } let file = match file { Some(file) => Some(self.render_file(file, lines, sections)?), None => None, }; Ok(Some(Location { file, line, column })) } fn render_file( &self, file: &gimli::FileEntry, lines: &Lines, sections: &gimli::Dwarf, ) -> Result { let mut path = if let Some(ref comp_dir) = self.dw_unit.comp_dir { String::from(comp_dir.to_string_lossy()?.as_ref()) } else { String::new() }; if let Some(directory) = file.directory(lines.lnp.header()) { path_push(&mut path, sections.attr_string(&self.dw_unit, directory)?.to_string_lossy()?.as_ref()); } path_push(&mut path, sections.attr_string(&self.dw_unit, file.path_name())?.to_string_lossy()?.as_ref()); Ok(path) } } fn path_push(path: &mut String, p: &str) { if p.starts_with("/") { *path = p.to_string(); } else { if !path.ends_with("/") { *path += "/"; } *path += p; } } type Error = gimli::Error; fn name_attr<'abbrev, 'unit, R>( entry: &gimli::DebuggingInformationEntry<'abbrev, 'unit, R, R::Offset>, unit: &ResUnit, sections: &gimli::Dwarf, units: &[ResUnit], recursion_limit: usize, ) -> Result, Error> where R: gimli::Reader, { if recursion_limit == 0 { return Ok(None); } if let Some(attr) = entry.attr_value(gimli::DW_AT_linkage_name)? { if let Ok(val) = sections.attr_string(&unit.dw_unit, attr) { return Ok(Some(val)); } } if let Some(attr) = entry.attr_value(gimli::DW_AT_MIPS_linkage_name)? { if let Ok(val) = sections.attr_string(&unit.dw_unit, attr) { return Ok(Some(val)); } } if let Some(attr) = entry.attr_value(gimli::DW_AT_name)? { if let Ok(val) = sections.attr_string(&unit.dw_unit, attr) { return Ok(Some(val)); } } let next = entry .attr_value(gimli::DW_AT_abstract_origin)? .or(entry.attr_value(gimli::DW_AT_specification)?); match next { Some(gimli::AttributeValue::UnitRef(offset)) => { let mut entries = unit.dw_unit.entries_at_offset(offset)?; if let Some((_, entry)) = entries.next_dfs()? { return name_attr(entry, unit, sections, units, recursion_limit - 1); } else { return Err(gimli::Error::NoEntryAtGivenOffset); } } Some(gimli::AttributeValue::DebugInfoRef(dr)) => if let Some((unit, offset)) = units .iter() .filter_map(|unit| { gimli::UnitSectionOffset::DebugInfoOffset(dr) .to_unit_offset(&unit.dw_unit) .map(|uo| (unit, uo)) }) .next() { let mut entries = unit.dw_unit.entries_at_offset(offset)?; if let Some((_, entry)) = entries.next_dfs()? { return name_attr(entry, unit, sections, units, recursion_limit - 1); } } else { return Err(gimli::Error::NoEntryAtGivenOffset); }, _ => {} } Ok(None) } impl<'ctx, R> FrameIter<'ctx, R> where R: gimli::Reader + 'ctx, { /// Advances the iterator and returns the next frame. pub fn next(&mut self) -> Result>, Error> { let (loc, func) = match (self.next.take(), self.funcs.next()) { (None, None) => return Ok(None), (loc, Some(func)) => (loc, func), (Some(loc), None) => { return Ok(Some(Frame { function: None, location: Some(loc), })) } }; let unit = &self.units[self.unit_id]; let mut cursor = unit.dw_unit.entries_at_offset(func.entry_off)?; let (_, entry) = cursor .next_dfs()? .expect("DIE we read a while ago is no longer readable??"); // Set an arbitrary recursion limit of 16 let name = name_attr(entry, unit, self.sections, self.units, 16)?; if entry.tag() == gimli::DW_TAG_inlined_subroutine { let file = match entry.attr_value(gimli::DW_AT_call_file)? { Some(gimli::AttributeValue::FileIndex(fi)) => { match unit.parse_lines()? { Some(lines) => { match lines.lnp.header().file(fi) { Some(file) => Some(unit.render_file(file, lines, self.sections)?), None => None, } } None => None, } } _ => None, }; let line = entry .attr(gimli::DW_AT_call_line)? .and_then(|x| x.udata_value()) .and_then(|x| if x == 0 { None } else { Some(x) }); let column = entry .attr(gimli::DW_AT_call_column)? .and_then(|x| x.udata_value()); self.next = Some(Location { file, line, column }); } Ok(Some(Frame { function: name.map(|name| { FunctionName { name, language: unit.lang, } }), location: loc, })) } } impl<'ctx, R> FallibleIterator for FrameIter<'ctx, R> where R: gimli::Reader + 'ctx, { type Item = Frame; type Error = Error; #[inline] fn next(&mut self) -> Result>, Error> { self.next() } } addr2line-0.10.0/tests/correctness.rs010066400017500001750000000034211346220724300157240ustar0000000000000000extern crate addr2line; extern crate fallible_iterator; extern crate findshlibs; extern crate gimli; extern crate memmap; extern crate object; use std::fs::File; use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary}; use addr2line::Context; #[test] fn correctness() { let file = File::open("/proc/self/exe").unwrap(); let map = unsafe { memmap::Mmap::map(&file).unwrap() }; let file = &object::File::parse(&*map).unwrap(); let ctx = Context::new(file).unwrap(); let mut bias = None; TargetSharedLibrary::each(|lib| { bias = Some(lib.virtual_memory_bias().0 as u64); IterationControl::Break }); let ip = (test_function as u64).wrapping_sub(bias.unwrap()); let mut frames = ctx.find_frames(ip).unwrap(); let frame = frames.next().unwrap().unwrap(); let name = frame.function.as_ref().unwrap().demangle().unwrap(); // Old rust versions generate DWARF with wrong linkage name, // so only check the start. if !name.starts_with("correctness::test_function") { panic!("incorrect name '{}'", name); } } fn test_function() {} #[test] fn zero_sequence() { let file = File::open("/proc/self/exe").unwrap(); let map = unsafe { memmap::Mmap::map(&file).unwrap() }; let file = &object::File::parse(&*map).unwrap(); let ctx = Context::new(file).unwrap(); for probe in 0..10 { assert!(ctx.find_location(probe).unwrap().is_none()); } } #[test] fn zero_function() { let file = File::open("/proc/self/exe").unwrap(); let map = unsafe { memmap::Mmap::map(&file).unwrap() }; let file = &object::File::parse(&*map).unwrap(); let ctx = Context::new(file).unwrap(); for probe in 0..10 { assert!(ctx.find_frames(probe).unwrap().next().unwrap().is_none()); } } addr2line-0.10.0/tests/output_equivalence.rs010066400017500001750000000067751346220724300173320ustar0000000000000000extern crate backtrace; extern crate findshlibs; extern crate rustc_test as test; use std::env; use std::process::Command; use std::path::Path; use std::ffi::OsStr; use backtrace::Backtrace; use findshlibs::{IterationControl, SharedLibrary, TargetSharedLibrary}; use test::{ShouldPanic, TestDesc, TestDescAndFn, TestFn, TestName}; fn make_trace() -> Vec { fn foo() -> Backtrace { bar() } #[inline(never)] fn bar() -> Backtrace { baz() } #[inline(always)] fn baz() -> Backtrace { Backtrace::new_unresolved() } let mut base_addr = None; TargetSharedLibrary::each(|lib| { base_addr = Some(lib.virtual_memory_bias().0); IterationControl::Break }); let addrfix = -base_addr.unwrap(); let trace = foo(); trace .frames() .iter() .take(5) .map(|x| format!("{:p}", (x.ip() as *const u8).wrapping_offset(addrfix))) .collect() } fn run_cmd>(exe: P, me: &Path, flags: Option<&str>, trace: &[String]) -> String { let mut cmd = Command::new(exe); cmd.env("LC_ALL", "C"); // GNU addr2line is localized, we aren't cmd.env("RUST_BACKTRACE", "1"); // if a child crashes, we want to know why if let Some(flags) = flags { cmd.arg(flags); } cmd.arg("--exe").arg(me).args(trace); let output = cmd.output().unwrap(); assert!(output.status.success()); String::from_utf8(output.stdout).unwrap() } fn run_test(flags: Option<&str>) { let me = env::current_exe().unwrap(); let mut exe = me.clone(); assert!(exe.pop()); assert!(exe.pop()); exe.push("examples"); exe.push("addr2line"); assert!(exe.is_file()); let trace = make_trace(); let theirs = run_cmd("addr2line", &me, flags, &trace); let ours = run_cmd(&exe, &me, flags, &trace); // HACK: GNU addr2line does not tidy up paths properly, causing double slashes to be printed // for for inlined frames from /src/libpanic_unwind/lib.rs // We consider our behavior to be correct, so we fix their output to match ours. let theirs = theirs.replace("//src", "/src"); assert!(theirs == ours, "Output not equivalent: $ addr2line {0} --exe {1} {2} {4} $ {3} {0} --exe {1} {2} {5} ", flags.unwrap_or(""), me.display(), trace.join(" "), exe.display(), theirs, ours); } static FLAGS: &'static str = "aipsf"; fn make_tests() -> Vec { (0..(1 << FLAGS.len())) .map(|bits| { if bits == 0 { None } else { let mut param = String::new(); param.push('-'); for (i, flag) in FLAGS.chars().enumerate() { if (bits & (1 << i)) != 0 { param.push(flag); } } Some(param) } }) .map(|param| { TestDescAndFn { desc: TestDesc { name: TestName::DynTestName( format!("addr2line {}", param.as_ref().map_or("", String::as_str)), ), ignore: false, should_panic: ShouldPanic::No, allow_fail: false, }, testfn: TestFn::DynTestFn( Box::new(move || run_test(param.as_ref().map(String::as_str))), ), } }) .collect() } fn main() { let args: Vec<_> = env::args().collect(); test::test_main(&args, make_tests()); } addr2line-0.10.0/time.png010066400017500001750000001663431332105314100133310ustar0000000000000000PNG  IHDR #/ pHYs.#.#x?v IDATxyչ0}_eE@auш(WA1#hH MԫQ4M\ƈ(UEA@da?*_߾30K@?S֩z$|H$LPPPPPPPPPPPPPPPPPPPPPP?O?=^/>SLMW_K/L689HBeI$+++==}˖-۶mRJڵ5jTJD$2-[L0a3gȈlٲ]v ڸqDe$25G5ȑ#~駟~2GVZ 'ɉ䫯7n\{-4k,P(,\[re~322y晩S?O/8Q}W /P Q e(֭۷֭[ t֊+.O>uօt5N=hrʅ ) see\nݺ~/~w^z饃Föo޷o?FW^yWH$T& pdɒ#wʕ+{ /y+VlԨ_`ɦ g;vx'b\r%}QFroܸI.؃cƌY~}1f $2ل 8֯__.[6˖-kկ_?zǏ/,kJ"wر}CU^F-Z(W\G޲eƍ7nXrƍ7mڴZjJ?{/{뭷֫WgU^{;Gy!++ۼy;jԨѠAƍ$:/c*S(C&M6m͛}Z\СCA_fK/oX"xjjE]t 7\wu˗/\Wv۷o_̿&ݻw?>qį7tرcÏ.\;Ȁyk&2f<1wy+v?^ze9tʕ+ݶmƮyp{/\~M*UT^]^x\rAS:x{7~_A}4hP>}_o/cǎǾu*T8233h^zKE7hѢn-|G?OW˗/?cƌGE|N_wyoݸqcjjjFZl9p+2g}o_lٲeǎժUkذg}UW]r%-mICp|#33'lԨQ>gU_͛9G}̚Ν;/]4̙Sƒϛ7/6I&5h ٳ'xZG"5kƞl'O xWr2a„ؘ?8gLlIG}]x|sN_`Z׿fee>-[1f{|I͏B#SO=ʕ+s;wƞ5r\Ê㛟9s1 *T{V̇z(4hOgzy֥K+V{%8Qڷoߵ^|ӦM<{=֭[wݻw7͡C;wG3}zE"C3xqխ[7gpJJW_=mڴիG~=P%,~%cܸq7tS ڷoP՛9sfǎOIIo؃jJCp|Q(AzH̦?W^ye۶m>SN]f˖--X`G=x6m{c']̃C=4r"۶me][ЩS^zT|5j8Z@ٲenj{dӦMFΞ=;~cǎͻs(;|2lذ?+gqƂ b5*n1*Thݺu1n۶mۋ/89Ξ=;'_Eot޽yyǴj*{5M6y 8R6 uԩSNAZdI۷o](I&N+W޿BUJSSv_of7to~x]%5k־}DCPhѢEv/sE-[ȑ#a75 EеkcԬYT*K ȑ#=wܹsc={b+WԩSչ[Bݻv嬒~/'ݻwPٶ9snjڶm+x(| #Nɩ4?T2w/o۝wٲe{lܸ1ۥK]1---QSO-)dff>s[~衇:Q>S I&믿fۈׯmٳ'+++>iA`/˗/Sr*KKOO9s+V\M :Ν;c͛7/͚5K๪UVAO5C.X G]wO?]nݢ_&cvZQF۷o_jՊ*_8? Pؿ>;a„ٳg}݅lzF:=bs>ublܹ@ڵ+QœO>^cƌ)y\ȶі-[U9:NXIPĝB w}G7nxeiTN_]WX_V%ӨQgyz݄]vlwƍzj)I-";2iӖ,Y֭[w͛7/;vΛ7@=rYgي{NH*aӦMNᄕ@ܕIt7w/~|V9r$6mT^=ڝ9sݻզMbwJx2dHF<2eJ2TApgv.]LJX}N @nݺgQ2eu8p`ܸq{VVV/n֭Ǐ_Jb\iөSGUO>b~xr,={'lĉŝI:*DQ(l߾=۴i{/a ?p1ڷoO< -=\JrMŊ/hwٲe|A>}իWX@YdӧO/dӉP$BvڱcA$ƍ;Z~{5ٿ-xz'"w]w <8v򗿴-k'%%+S'ӧOOKK2eJ΂Ç;o߾{l֬OJ7:+5558pW_}3СCw/~Q)7$:8*R¯?0`vլY3={̚5k„ /rtjժٳ'zְaÞ}ZjevO=ԏ~؃?+rwܹaÆK,?~|7püyVXG:x!,\0y͛7nz鋳:뗿o梋.jӦW_})ԩSgVzwsSRR^~jժxVN.wߍYtiǎo?]vժU۸q)S^|UV1_~y:u^|eoيu?hѢ]v߲e9眓Ċ~J#@<<=oAԬY3##c߾}6lW\qg;N:ab aÆ#F<|ǏkVݻw_کSc_Ԛ5k>qj;v_{pŊ9 z*Gc8rȘ1cƌk|ǎ_{ÇTGաCU.]B;:@i`% 7xB 9?ڵkW*jժ=sO?t=rаcǎu]?xrRJ̿XϿ̣?RSSy_ױVZofqomڴy뭷DkĉUV-iӦ;wNt~J+_g 2dG)SO~￿~AT\'2dH>/1|}6,vlʗ/__oÍnᆭ[McǎH$RqФIo=mӦMΘ .`n-5<=>|ԩSP 76hР[~Ν{-|GX#OTi믟}yG@ R &%L>}„ fZ~Ν;VڠAVZ]veW\qE_}DOC@ eH k eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH eH e&:YfEd֭*8L(n e?Lt Ç@z PPPPPPPPPPPPPPPPPPPPP6 @R{?ӂO~A3w `РAK/r??3n_wqǒ%K}.]GːX%nϞ=W\qE$ SN~ǏGq饗| 7lڴ)Ueʔ ;?~O?A~|Gy7f̘VXqȐ!]vYܯX (%==}ҥUTIKKKt.QZ-[:333Gs#2=== ---){nŊܵkݻ@aXQ˧~D>D0iiiV WnӦMa۷oo?<33h󩯾*v[op IDAT߿?/FNNp°]vM֯_Į_RB .]gpٲ_U֭[7*UWfG1k֬ zwX3(:undɒ.'޽{-[vith;P&?۷ApdǢEyw}?;4dPJT2eʗ/_г 2dȐ'o\`Aٲeuwd2(;v,SLVVVK.ꪫr [`AHIID"A̛72ժUkѢEx)amذ!l\tEuLJ7]Hs>|K.+WNt.TJ֭[%K-~6͛k#G/_ʔ)կj96*ULTϾĚ={v{nHN:m۶m۶-g5kvA5~-[gϞV:|pرcd @^޽{.\w:taÆ5jٲ19gΜ e֭[bŊ۷רQI&-[X~_^LZjk׮I&pw_KtIϟ6tҼyN:i۶m23zw)Ν;G‘Hd͚5+Vعsg՛6mڲe˪Uǵ3H$r5kرjժKKK+QK~D6mڴqM6edd4lذq͚5;Pcǎ7n\ ;{M6k/䒲e,YgϞ׮]?駟`Ĉ^z {책 ƞ[j՛n?ar~yD"fzl5k[n9RRR};ھ}^_|œO>9װ#G\uUP_'駟NL,Yһwl}v횒ҽ{?sQ(Sz͛~s+ 1 GѣGl/_#Y&`ʕx5TX1??W^8'N|ᇃ 8G=^V$裏^x͛7/W\޽o6?a޳"#Ȝ9s^~+VdqƷrK^J]P?pš={7}ݗf~Q~U;UnO?=lO>ha}YX%SJ\߀%rʧzj^dIO:hѢݥK vv͛DWa#---ӧO۳UA˙Ob<٪d Ș4iM7ݴlٲYdffQFJ&7=*@r ,X6|CzgnݺZj+V?~zzzͻ뮻?\9\*HOOw'ڵXto} >s=sΉ]aرO RJ^Zjz?x޽A|*T;xG9{AL>=sl&M6zUB&_:u \V^}uY/^AӦM]t@}oE;vlݺ5lw=3n zAп5jAsӟ˗O<933UVwީzС leʔ)=z8yݓO>9~wAp6h N;혧_fX>ԩSvƍ{]~۷_|E_~ڵk;)!^{mƌav\pAF"Ȇ &Mo߾ NzYg]tE )[r Ph߾}=PX_ҢE{M6>aŲey睫:k׮ݲeK&M5kV4b꫇ӧψ#{ѷoߡC裱%ATR{}sn]d 8|p֭G 7o~׆lKI._{coAPfxaÆق~G 5cƌg5С1OڐQ u$gyfOCѝjԨ\hLSN8p`^jU/ZaKa㬳6lXEF{~X2\vmfLÇsի?+W,}@rR('H${Eg? ۷/ٳgq- oNIIybĈ#F <8\2pٲe˦MywuF_fmVXQVm+J*uY~TV~GdɒH$Aʕ/ң۷jժAD"+X<3ڵkׯ_Ѷm-Z AfҥYYYa;R۶mT nݺujՂ /Ã˗/6Zծ]O5jrqQ6Zju7ԩ3lذA 4ȑ#-QȦM &z֥_u<=v?ݺu{G_uhҤI@[j[ܰaCp9s=7/5jtPr=^85kVRUXy*5˗/YS;C͚5;w>mڴA|Ga#---7@;w~W طoߺuZhOvڵkpyu=+VD6:v 5j1[m۶c Ҩ(5UV֭m~yׯ[n.iB8DްaC޽scB8fUEٵkW8餓lРAsΝ9?޽{,D"'O?x9ڷo_\ ,YҢEH$rB u- DY' "ΰv69+D"SRRޟglwܹsMMMmݺu:uԥK *hL xv]SAwޅ VXsq̪/xy~WрM:2Қ5kKYfڵ (I˗dɒ ֭[mT\]vUd°m۶ARAбcǂ.Hʕŭ3={uC:Gg-Z֧Oe˖?~ȑW^y>qƂ IΊ2p)[^~|vߠAhO?ѣG%)]!z_,9tP(ޫVڭ[O?4iӦxADٳg*U; :whѢDIKK9}SN-"p&N:\ D;`2 htYd:u~_6lٳfZhQ*2eʌ3~%pS('U s==}֬YA]*"E~F޺ukޑ7oիWcGӻwPf7xcff)S.Hȧh5ƍw)Խ{hL׮]uر-KjFHO* ڵk߿GY|_~9{NÏ=X۶m[hߋKpiܸq(Œy楦uYΫ`r9hl6VM{Vڸq… ÷uMq]vmt-Z.A.]r֭[ؘ?ŋvZ7o^̙6miZ+͛0a„ VXQkYdٲeO;O3fLhff;SLWeDӾ}iӦuOۃ ۴i_|N:E(Ek.llܸqŊG;e͚5/> 8 |TR3 W6m?J`' ʕ+סC AocaE.0Q֭[s~79<8eʔݢE_B8ٳsa{衇֮]D 8tД)Snp˗/OOOoݺuyE~ 0 0>w}?|zzzQzz?}eeeAP~GrhbK.V^NkС ==o4iRVffe~G~qoN322>;sa%\@2(+S̯~Çۙ~aŊ+W}>|x˖-vZN&(]Gʕ}{|W_}ZjAshXժUGUJ8P\pӧO۩\pAI^ȧ38cܹaUVh4iR~[ݎ;mթSgAԵk׼SRRbIKK+E6>hѢ:ܶ5RSS_GD"6mZtiX%Ӽy8V W^<@:unff;bd#FdI*wY!CMk׮}wzq(R¥9D 8rȑp2eʔ-[-Zr ڷo߾}a322 ([v@_pԩS.\ٴi&Mt/pmܸo_믿vţerEAЬYl+Gڵ+UJ*G[,:wQP3gΜ1cƲevDjժծ];/u6E222ݻwAs9;M6Ed 7Ͱ zw͛7-[^zÇ?3Gjjjs933Ad:*o޶mۂ ۷oƍsyӦM۰a֭[WޤI>}?XC{ 7n|gGϊ˜'N5kֺuvUbwԩ͛7w7͒E֮]]v۶m[l)W\Æ 4hЩSK.B @Be@qS(sQ('ӧ5*5k?(e@$BP`%R_Wӧ*R(PZlذaa/Nl2'N eeeZꤓNڲe?n١CVZ%:5BDD"v[7|sJJJB8z tOڹsDgp @u}ɒ%eʔ9S Э[DgpbR(H?pH ^ )( )( )( )( )( )( )( )( )( )( )( )( )( )MtXڵATXjժ;"HSժUPB>rȮ]pUVjjj>p}Q+U, N:)))a{Ol>(55VZݻ>|㔷@QXQPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPf]^nnMC$+l * :ʐ@:c:ĎAVE]XHAidMczntzis^=ۮ>_B"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"4{_S+oŇβ 2DA(@ 2DA(@ 2DA( IDAT@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@RR 666{ ٿ=pET#\ ccc Q(sرzEQreP\r\] w:u 7̘p'Ow7oɓccc|s-JSN:Uy^xOi7sYf4׈J2zO2ןzEQm>::p QT.͹LΜ9 $6v~d0; \^ PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  Bc{[aGQB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  P<8Gvm 7[ˣ,X1`Z2?+2G-[jyԦM6l0`Z:|pG`rB)knnnjj[aQV\Sˑ]xCz瞻Cp(S={T++V<5~Ea2j#ӧo^EKK?_*νw|G a8j#[oUa}َe(p-Lb߾}===EQw}\],Zhtt>:?gΜŋwvv_~Μ9WunF(sQEQ><毿.N8y=z={{6mILp@{{{ggg\IMMMlnnT*KsssG}OP)|P;?2v;=szM$ Euww Ec͞=nj1ՍgfϞ=888phhhǎ޸qOOp]wݵf͚?Z[[=׍rӢLV.xS.]y ȕkkXG&k>(y=;lKEQtttlܸqʕ/?j1ݽlٲ* ͨרwygdd('xbm!wYlkvryٲe(Z[[ׯ_?O>pQwqw;~(ݻw{Wfj&"]vUzꉯ}=Lz 6 E1i(u֭[N|Is#GT>ô?~CCCu}UꎧPwR<\/dywkִ Js󍌌|u.ryҥy'eVwYd-2-\xquqĉi9!S%9ߧ~Z][n|?4~YfM zpm駟(Jk׮CL{{M74Gu1)o&>.bҥ۶m3gΜٿu}O۬LK/ݻwW˗/ᄏwv_ET윎12Y{kez/5k,X0M05B;22R]ײLSSSO=U]⋟|ɱc*sΗ^zipp(s X!?cup¶ZzEQ9rdǎ;v9spR?e˖-Wblj!9kl |iҥKǻ OPȈw APdɜEvDňg8RRRboٻwΝ;DLffED]ݻk׮86@13 ǜNSd  6 eABAPP eABAPP eABAPP eABAPP eABAPP eABAPP eABAPP eABAPP eAB!9 [w 9 (F(<;|[ceABAPP eABAPP -ҧe IDATeABAPP eABAPP eABAPP eABAPPHweD[0dƭ Վ? eABAPP eABAPP eABAPP eABAPP q;/- P^1-pFBAPP eABAPP eABAPP eABAPP eABAPP eABAPP eABAPPHwSVVٳ-[f͚רQUVUV-l~_v/}ݛ֮]ۮ]XJ&1~޽ `Μ9]w]VV\r|AƍǏ@J&yĈm۶]zu~:BEP t6o|̚5+a?6+k׮:,]41+V86{?ɒ% x/_~%I:v}. @kѺSN&M? &O|UWw>|x޳vm}Zj6mu&6`߾}ݺuA&Mƍ7o޼իWϟ?gqFի/̃Zti==LJJӧG}lٲ%K{W_}uҢE? ?TR&Mb8w7|s=֬Y=9v^zrYf_>:u 6쪫JII9`?`᭷:z'|gxcǎc>>,6>ș xLP zݹsܮ6l0r x㍭[1K/TzC^z׶mT#$$$6ѣkԨ322^}՜W!Cs9ӱcݻ0N2atw=o߾UVֻwtH]t9]zX=ph2e;aUTRλ4ipErfݺubڵva O0 <eBbŊnݚ۰ *v)]l͛7N3(s)sE $eB'555?J.wQrULu+W.Vo۶-Zdddr@BBP toߞaJ'tR*[l޽{w>9TRѢ|k֬!(:ϰ9sSO= UR%V/Z(.VW\9Zr)L\2_]!(:ӦM۵kaUVXvڱlڴi函eڵ7ٔ*UQFѺuֱ1s{7X='0Aٱco+V|6m`-ZhZn޼yJJJn֬Y?ӼyFP ތܮF"!CdggGk׮}l] &޽;{?~|mNNNݻw#sQFa&(Fk֬իDᄅS 0 ))` ݻtzʕÆ ch]D>}zM7y :4,|ɓ۴iS^H$dɒ/2͛_|ţG| Q&!!nݺh8Pӏ>l׮]Ѻcǎy{Ϟ= .֧vZɒ% *px1bĴiӢ3ڴi{/9Tǎ{s@q Zn|H$ȭ[}ݱǷ3xӧOb5I iӦ}w:tXdIsm۶mu a^xWm6v ^z饫I&uZjYYY1>lRRRA|pʕZ0##駟mpRxO?:[/Pl+?I'N:OΝ 1XF_'OOΝ~;v-[WUڵ۷oߩSf͚ŻS1cƌ3&]3eʔkx7'2nr[ RneP$ƻ( 2 (@( 2 (@($ǻ ݻ1XtxwK2DR;]Yw @qe%BAPP eAB!9 ٳg޼y˖-[lٚ5kvؑDʕ+WlٓO>nݺu=sJ,f(Nٷoܹs?>/ܳgao)Qį.}sNJJJ! @Lvv~:a„O?4##̌k޲eva:tHLdɶmƍרQK.dʔ)G9@FFƔ)S.ƍ?۷o?V}p")7ʬ^z̘1/Ν;#9OoѢřg_*-----RJiii 6mڼyM6m/|7fo~2dw}qrJa~iqٿ?~}Ȥt .8>RJv{իW~ݻwϟ?_|Ň~w 222Ə/>NNR)#={v~,X;ӦM޽{_q*U*Jjݺu֭o-[L<_>}zr={1(nٲe4%SjՇzh3fׯѤdPbnaڴi+W5jTjՂ ?ywM7U({PfHRJ?eZjN=ԻkٲecǎMKKD"O<[eʗ/?|˗~eʔ9E.]?8|΢e{˗-HeuFxdN=(EA dggG"xw@gϞ=Gz68twaâ֠h)rAݻwO?ԯ_:L2eʔIOO{֭[WPL%ǻ H$ ӦM۵kQ)S\wu۶mYhѢEƏ3\q/{lǎA߿rnevqW~%J0`Ŋ\sMFFn۶JNN֭qoШPB͚5 (_|{򗿬]6=z)BLvvvn1o߾d"HlnXy衇zxw_ū[.IHHyx뮍7nݺ7ߌ%c6m裏B_ D"úuN:~9_={5jTZZZw>}>M? mxnbŊ?Ѻjժ_u o;#ƍ_}?|?~[[~v5jk׮zG?w}7wܵkV\AgqF~BD.]lٲe˖eff֩Snݺ7NNgxQfΜ9zСd6lذph]vO?z_4(6nx47n+k֬٫W?Cٳg͚5/v[BBBBB°ar=A?\pM4kξ}m۶VZ233o߾{x|cz=CEϬ]6zq3SLɻb$,n3f̈:tHHH8`@ڵcu Ɏ;uvKׯ׿5gΜ 6deeq۷_~Y /\f#G}O}%Kr9sX~ *U߿nݺhKsύYYYWPhN><֪U+V*K>+==ٳgLVV֜9s}.J*W_}Cru[op ?_xᅼ_sYg{)))n`Æ ѢzOfϞvڍ7+WO>s.X.槟~ʊ5kmU&&&F8W>Shfyu&99 8yDŽ p$IHH 5?1a&m۶UT)۷o˗/rD g5jL8GywL2mڴ؋d222&N[o?O>e ڵk۶m'MGYLX'S IDAT25:z]D:nA,YhV駟/[lٲe… _믿K.ycdOٲes?!!\r۶m;C=z|ǀO?{ 3 IZZZ[N& ϓtE{|UxqaEaY˗/ce˖+JG*JWޯ_~ݻwܹӧOw ӿ-Z4mڴ0[㪨B  0`aG|̓nذaFIt4YzudٲewKڵk6lgϞXlٲѠL[(K.袋rxhQ~RJVS3SRSS[jժU;cƌom۶o߾'|'KKp<LuNz)ʕ+hٲeɒ%ݻjժ/bԩɓի׺u[J*me ? 7] H駟-[,~wHd{?C]tQNpr-Æ ? S s7ԫWoĈwä֫W^z-[>|xfff/yݻ7:A7k֬/ /<;S`hݳgF,{>y 6mĉm2(58̪UN=4p5D#/AiӦ=zxW X~7oAjjjta/v)))yڵgǀ') uVxE_>L"(ŷ%yқO{-g@8Q-P@81L"Hl oq̙UVy~8p`_o~CݺuŔ)SF-[nsᕳ>;-ZԤIܹ3: MZPL pwVVxu׏5駟 &7g}a֭ۻᄏcǎ bA%JDڵ+;;;111cr,Y27o<7n|x.]V^믏3&ܧz*u .{aÆAdee͞=w?cZVX</NOO/pݻw;߿o߾-[>W]uU5233?Ç7_}"(lDZw{nݺwu͛rQ6m;ԩ6H:k׎֭9w\ڹsgݤ }WU'@Bb)"8b;W"̠*ΌEXF@AfPq,tņ&H/$=7B$>Y{ssɓﬕ7nd֭Ov'_~y˖->W^Z7o^LK.dgqĉraѳgϖ-[6kO>96 ֻv4hPժU/^r… mv7m8y3lذw~IzVzz_=p'|r޽?pܼjժasΰȸ%WẊ~GyG<'L2~\h@Ǐ?s×˖-;wnz͘1㬳:=zž}f͚5>G8p`$ٳgÆ ї*Uzg?NKCѣw1cƌ;w>O?t zգG3<3GbŊ &?Ctu֣F 7:qarqqqiiiAlذJ*Y.ܺuk|h@a@qqq<@ǎ_}>lݺu >3۶mۣGg^ޮ]/͚58޲e#FAPn=:111STC.UR嫯7nodɒUV-[ѣM7TX{kkժu{PBG^|yBBBbbbr7)TOw̘1-Zjʕ+Zjկ_?G'Luԙ6mرc y -Zt}w}-ZhժUӦM6mzgm7nϟ?ƌ}YK˗>|x޽3߲rpr.ZfMX)S&, ,XZ+WAW_5n8˅ . B E7ऊD"ŋ8Rn'|(_ve]vYF5j(gq=s ۷o߾}ZHí뮻뮣6>>>+Df 4xꩧwADӶmۑ#G=_ ̙3gΜNJJjڴiÆ 8rʕ-[6ozz֭[lwӦM_bŊX~=-[h9sI§9p9x&M _|q-d/ fIKAPr? 2dĉ=3^_~7|nެY;SK.F9à/O?իW/i~aN$iҤIt /ڵkW^]ZC۷믿M '#z5o޼?_~xtDr˂ XlW^~zǎ,]tܸqaݲe *D/s9kW^y%==={ (]tV7rP 2Q^x+f͚~ԩQT|.] ?ի_~ .z(TP>}zӦMsG}}/[lر JNNTRɡH$һw^pwܻw1c}eIN\H$RN:uMKK[tu6nܸaÆqqq+VXbJ*VXJ5kX.[bɓ زe?'$$߿?1Eʕ+w v `֬Yͫ^z$Yjվ}hӦMN5 q}P&ڵkG3H䦛nTرcwdSvᄏZjYoLHHx߿dɒWo98VP&V"W_ݼy>lW޶m[\\\ٲeի׼y&MdtD";wnڴW_m޼9--\r׿ꪫr9@eWůꫯWV[nٖ)qnr BX7@nOXw D"n8]  19z |AP|TY_}իw.]}ٱ )IMMoϝ;7999ƍA͛7_r%[ӧOf"H8ݻ7555]䀸Eƺ teΝ{w~WGdɒ%K7oK/իW/8ݥ"$74-X7A0q-ZMJ&>QF'N(3k֬^zGG/~e=tˍF88(ܱc/#oۍ7N6W^|IY,2#G8qb͏r^8mڴ /G}o"A˗/]4۷oߺucZ^~[n%o߾p<$Ae˖E={z,X=GxGhݰaC:uMr'Xev-zw(^x޷o_@ˠLJKwC2(Szh=}ԩSubbb@ˠ%\Rdɰ~Lw/u$iժUζ@^ˠLBBBzŊ :[zuy*T+b NHH]v_jӦM^{ɓ#=jy\ժUÏ姟~͵t ƺC%&&8pAl۶mE)SL%"Hqƹs*Ue˖%7O6msٸq֭[K*UFVZ~jՊud dPRJ*ź ;SNMOO *^N_~nO3nٲe˖- ,>|=ǪC@L.]:111%KƺSÙ2eJ:tu#'ݚ5k7o~H"EJ(믿/,^GGfyF\SΟ5k֬Y{u/V3YJNNO㯹Xrrw9ر_|qM67.zlԩS?=O߼DP8!}Ѿ}%Jĺk̙?&MjҤI$ |z9p“O>qƘJVN6lꫯ.Z\zq7޸s1y ڷoFN{.,6l#J._piii2eJsM+Azo޻w9yOJJӗ-[\jVZUR%G|ӧ/YdΝ*UKk֬yȣM>f͚ի_~<:ݻgte˖-[,%%Fa f.8xԩS h׮]RSSovATV3Ϭ_~ɒ%]Or={$&&6k֬VZGNOdm(g_z]@,W5jԨA~m٠̏?_]|knذ|۶m9s5kٓTV cb>}7ޘ6ȫO/پ}{t@ݻwJ.]jյkז*U*A ><~xС#G0 ^z[o0a½޻aÆOԩӫZdѣGuԡC.\;}vz\Ŝ9snڬYʕ+riǎ#F_uC./^n0`@jղ֭[x^{-%%%x_| do?5kք/lhԨQٴiS6BGöxo}̙ז)SfȐ!͗/_>x)S} *,\'ضm[smҤw}Av5j,Z' K,1bDIصkW׮]G…+VXN?MT\{5jHOO_xqpƛoyuۦO2%:r??):up ժUKOO_z?ŋAe˖;㐸֭[/uօ/TҥK5kn߾O?9stͬ#~V{ n ;ƳyQڰaÐ!Cvq9t墋.ڿg}6 +ڵ;O>SN;-X^ۨQe~׿֯_fΜ9gXePZŋǰѣGY ~|@^[ϟ|76mZ"E&Mt׆#W^yenׯgϞ ”̋/xEnݺw{n5kVne?_Zj{ F/ ;N0!Yo߾=zE ;tзo . y:ujƠ̎;dׯ?vƍGܹ;7n\Qacɒ% 9>hXtMCd D"7|}?*eʔ/BƔLʕ2dHXWo{d.\u}G9)..s HKK믣֬Y믇u.]{h%ԶmW_}5x"k3:gu4&M?3% dEuҥ^zOd!gϞt%--- 6?YK.$,28a=lذʕ+gygyXbAر#zVTˠL ¢DG9"zR6mԩ *tf)tIIILeEڵk>;,RRR{*Tp8$z VPiӦbŊ+V<\K۶m<8{ܹsڵ\eJDftp|ͺu92SG}Tt飿I6/~ueybŊWX|nYbbbfzΜ9'` hڵkٲejՊa3% ,Fe3;g GRRR[d9x>'|2KrK6m+:s IDAT LTTQFJ 裏n֫DG!L{dc߾}Fo2_+%K9'6}VYZ`͛7/:ҿzh>Tfd9>]vx~i/>6O \tEgyU e)֭ :+iժU;#N8A֭(3q /p߾}cN }]ZlYlK̙Tp &d9'flڴiX3&zSfrvQzG?.Rqi֬YX,[f=ӹsΝ;/\0WZeΝ۳gݻwǶ ۇŖ-[2eʲerS̙3>|^xpsq԰ܥF&/]ts;w 6=:˵˗/0aBή=ѵÇ/Td+[쥗^Æ ;ܴٳg?3'Oԩ[X>??3UrE}u>y[ڵ?z/_~ ֭4hP;4nxA|G?C惄 A4h w}7vey *Ŷmܗ_~yƍǛ6mzA 2Yf}btMNN=ѝr̙s%UTQ=Du]g`ر-Z~o9obŊv1ˠ7|t?'xy9r3m֬Yxk׮UVݲeԩSz衍7֮]{AǺر}w4k޽{*U"HJJ'|#|70Z`7jԨzY ˗Ϙ1UV ܹ3ZG"QF5o<==}ݗ]vـzUf]v}'C]dI+W^~};ڣtҰؿ_~4K#GN\NO?4o>8p` "޽{2dŊA*T(_%byҷ~?_uUR2Zj;6<g<@Z .ؿ7֩SgԨQ|{IRRR4'k׮AUZx+W.\p۶m,X^Skwݻu]o+Vؽ{wJ.~<󟃬v:GdX}Abbb8TRVPaԩ3gΜ0aŒ3֯_Zvڵk_y})X0ovn݂ (^;bidͱnJfSrY|= MO? ~3*_>vy~ +xٳgWĺ<&Da"͙3~Xxq$V5\1qƿok֬93[juEŰ[X&?߻w^xq6(8&?Í7A2eMQ;Ǐ&MjC\\e]venBŊl|.uYW\q> Ԯ]{ժU|͌3>,|} СC6@O;z' 2dH'`_G|vu̘1^=xquׯ_rb%biܸ?={ڵk7k֬@WT)۷۷jժW\qE=.ŋtMv VZOU1|m|K 2 2 2 2 O:h]j9sxWyIʬ\{}ȫ@pwIHHȲ+W.GRP@^լXw"H[NW'=(o߾ln޼d7@ ?@ (@ (@#zO?tJuu~߇QJ,!{MMMu9 ..hѢ8-8(oСCcyBBBs1<&==*.rs=ĺtuz1$vv)̜93Zoٲ%p˽ngsXbG۷ё<-2ӧO_lΘ1Dn^PzNn38#]pʽeNҥK|Æ u#r/(3{CUfJJJ:{*TB H$ O˽LʕZj\k&. @nȽe4nܸXbl; oqPW^m|K 2 2 2 2 2 2 2MCD"H; ./ gϞz#G0`@/ҭ:a„{wÆ WuW_-Ydzzѣcǎ#G֨QOOO:uСC.\xȥ>c׮]̙kVZ5s9'{߿r[n `=z8E,G/u-,vpӖ,Yd 3O:t7xHp$ɓ'i~wqHp${kٷoq4]k.sJ&G={LKK G[h'NiҤ\׿>wygR7|s%`P6Ap vZHS rݻw7o^ *yΛo}d5mڴ"EL4k Gnݺկ_Ϟ=A|wA⋷~{$ uֽ{>s׮]Y^JJ_ر WڬYKA[o+ܹwߝ;۷oo6scfQ]ym۶M>=E}aev$|0 uYӧOʔ)3xEE6z2d (Wܐ!CWTe˖aݍ&ɓ'APf͛gpe \r4,#sZjUF+vfoذa~衇2OhܸqXl߾"!!lٲ'i楗^z饗K7tSƤKTL,8A ޽{XL2%c$K}r瞛yB aQt餤l&>;,RRR{,o~(P@tcǎθd3f޽{gܘY8q2AЩS AiӦٳggp¥KAPxΝ;g<\HYܝ% >·s*UԨQ0`@6m&Ok׮#38+C6?~|Xlpo*,䎂nN e˖ &OܪUv2]v-VX⎰W'bݺu'ORH$2nܸ/8 |~a7nܢEVZ]yE&ݺu㏃ 8q!C.{97 %=zNKK{뭷oMgW~~)y ,1bD+Tгg%Kd^x 7*T(ov~hѢ )rs%(]v+֭7o^88o޼իWAPV͛Z3:tH?;3*U?~ݺu/5\q ݻw?{W2eꪰ4iRXDرcɒ%O{VDmۆuأK7|s$MgGro>waÆ]|}qV1u-,&NAjjÑ>}V{ee<})===55 ;/xsΝ5kVR 8pQپ} KN>}ݺuA$&&n:;`SH6mJ,s+V,\pǎ7n +VZ;ѣ/^A֭. :4%KlӦ͔)S 8q?ݻ@'s A_ ƌIn|1+k3g K石 APHHMM|[naP7Xre8%*G/=}iĉ&M t:tiSYkܸqX|G?C a& dжm0I޽;.nݺ'c)A?Zn]| -[(ӣG… Ǻ,tر`A8pYfÇ_vmzzz)))_7߄xm۶8rM7!6e(TP.]27FARRҠAz׮] Zj+W\pm.X :xMfy]FB ud "(9sư=D"ё={lذ!RJ>?~;\{Ŋ 믿\r'[nNx mPBG3Q?}7 'HP)>>>>>32dǺ) ^@|A BX7@n(XਞbEn8c@9z |AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|AP|`*T(- G2N\&)P@[e TL"(s)UT[8X7$! IDATWpeMRpO_yUN*_&@8LRSScGK )6oDN+8I\|{NYR||%''8psR8_!o:-IfGAAAA[Uegx4M@K@FF)zPԕEEevM'* ;dt$+tpJsJq_=3ꙵZ^<5|gm PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"ePW 7on'N0aBoOWggM>͛7߿?>|I.ɓ'+WvK,?~E @w eO7nliiiiiٶmۛoy7.ZbMMM}8MNQM'/477w}V2cƌzᇏ=cGk׮ݸq v>}wٝSPrVC:ڳB,@jOnIecÆ /By|uם~]/u1;w8rȿƒYiѢE'}~'ᢋ.Z|}zɐ!C=`0=w0X,@GV{ tK][uKov3f,^z( &,ZhܹCmkk?wy\̬[+E(s|~s=\2eʔUV1ݺ(C9c}}}CCCCCܹsWZZ??gΜ>M(s۶m{gnڵ_dɰaVU ._~(ٳq.o=yYf`:,A@EbqYRL?@Eb6e׋O[[+o/(ӧ/]/>^zI9~(2˖-[lىOlT'W{ `зɄ>|/ ˒ *:tȑ#=?OrՀXl08 +ۄ2e˖'|r׮]Ǎwm]{555=9m}}36mTůZ e~իW$SWW`niȐ!9ԩSˡ́*rB-LQ'|SOsΊ+MVחÆ i>LwիWsν{駟O?~gy=`ر=,H(S꫇.b̙mmm7裏֭[WŌ3xRt:::vQwy1^M'Pe;LQ\rIy?nٲ777EQ*fϞ݃pҟ(y涶(J͛Ozȸq&MTŬY&LP`}|̘1y/Ry|UWM8Iev]?9?ҥK8/^cEw+Vzs3f̑#GvܹaÆ7x(1c,^>'455+rǎzQۚ5k֬Y3dȐή݆rtPfϞ==9T*-ZhҤI/bKKKyckk{w}izFPz( Rq޼y6l/vܹo߾q͚5k޼yg.J-,=#G666666V{"_M'}A(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ =cV{ '^ d@,A@g1z.g%>|xMM+0X,@jOn <՞%) Vb ? s9+IT= V P*E(3𴴴T{ 'W_ d@,A@׷ɨ>|/ ˒Q*:tUa-b6e9zj <՞%) Vb ]LqYRPȑ#=?OrՀXl082Rל@Ee  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB&4z9y6B)ZVQ4 [AnEp!EEt}*PW/+]DԷX&ՙ$'yV霄%>DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2Oz AIDATDA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ ^1==|g?C޹sC=o߾W@(zw|Vé'N<#?pK7x׻Xٓ'Ov( (ӿ/wީ}=swqGQΝo]Ň~'ݻ,s<>hkʬ~zttN_gg},˦ʬ,xCgϞpBٹsw߿ʬ={>|-  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e  PB"e0ftZV[_nnv`ZXXt:0X#V,zJUUPr4Џw5KDA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2DA(@ 2D3^I* IENDB`addr2line-0.10.0/.cargo_vcs_info.json0000644000000001120000000000000130070ustar00{ "git": { "sha1": "85be6c7440051b443cee310b418065c63257fe70" } }