diff --git a/.github/workflows/sync-with-master.yml b/.github/workflows/sync-with-master.yml new file mode 100644 index 000000000..a6a7a4473 --- /dev/null +++ b/.github/workflows/sync-with-master.yml @@ -0,0 +1,21 @@ +on: + push: + branches: + - master + schedule: + - cron: '0 0 * * *' + +jobs: + sync: + strategy: + matrix: + branch: + - 6.0/stage + runs-on: ubuntu-18.04 + steps: + - uses: actions/checkout@v2 + - uses: delphix/actions/sync-with-master@master + with: + branch-to-sync: ${{ matrix.branch }} + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.gitignore b/.gitignore index aea926634..066854108 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.mypy_cache /build /coverage.info +/cscope.* /dist /docs/_build /drgn.egg-info diff --git a/.travis.yml b/.travis.yml index e3da1b8d5..10bea5571 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,169 +1,27 @@ -# Generated by scripts/generate_travis_yml.py - dist: bionic -jobs: - include: - - language: python - python: 3.8 - addons: - apt: - packages: - - libbz2-dev - - liblzma-dev - - zlib1g-dev - install: - script: python setup.py build -j "$(nproc)" test - - language: python - python: 3.7 - addons: - apt: - packages: - - libbz2-dev - - liblzma-dev - - zlib1g-dev - install: - script: python setup.py build -j "$(nproc)" test - - language: python - python: 3.6 - addons: - apt: - packages: - - libbz2-dev - - liblzma-dev - - zlib1g-dev - install: - script: python setup.py build -j "$(nproc)" test - - name: "vmtest Linux 5.6" - language: minimal - env: KERNEL=5.6 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 - - name: "vmtest Linux 5.5" - language: minimal - env: KERNEL=5.5 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 - - name: "vmtest Linux 5.4" - language: minimal - env: KERNEL=5.4 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 - - name: "vmtest Linux 4.19" - language: minimal - env: KERNEL=4.19 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 - - name: "vmtest Linux 4.14" - language: minimal - env: KERNEL=4.14 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 - - name: "vmtest Linux 4.9" - language: minimal - env: KERNEL=4.9 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 - - name: "vmtest Linux 4.4" - language: minimal - env: KERNEL=4.4 - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0 +language: python +python: + - '3.8' + - '3.7' + - '3.6' +install: + # Upstream defaults to world-read-writeable /dev/kvm. Debian/Ubuntu override + # this; see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=892945. We want + # the upstream default. + - sudo echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /lib/udev/rules.d/99-fix-kvm.rules > /dev/null + - sudo udevadm control --reload-rules + # On systemd >= 238 we can use udevadm trigger -w and remove udevadm settle. + - sudo udevadm trigger /dev/kvm + - sudo udevadm settle +script: python setup.py test -K + +addons: + apt: + packages: + - busybox-static + - libbz2-dev + - liblzma-dev + - qemu-kvm + - zlib1g-dev + - zstd diff --git a/MANIFEST.in b/MANIFEST.in index 8c8aa64e9..8255679b9 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,3 +1,6 @@ recursive-include docs *.py *.rst +recursive-include examples *.py recursive-include tests *.py -recursive-include scripts/vmtest *.py *.rst *.sh +recursive-include tools *.py +recursive-include vmtest *.c *.py *.rst +include util.py vmtest/config diff --git a/README.rst b/README.rst index 9e5599259..3f6d8edc3 100644 --- a/README.rst +++ b/README.rst @@ -39,11 +39,12 @@ Although other debuggers like `GDB `_ have scripting support, drgn aims to make scripting as natural as possible so that debugging feels like coding. This makes it well-suited for introspecting the complex, inter-connected state in large programs. It is also designed as a -library that can be used for more purpose-built tools. +library that can be used to build debugging and introspection tools; see the +official `tools `_. drgn was developed for debugging the Linux kernel (as an alternative to the `crash `_ utility), but it can also debug -userspace programs written in C. C++ support is planned. +userspace programs written in C. C++ support is in progress. .. end-introduction diff --git a/_drgn.pyi b/_drgn.pyi index 2f665ac11..0e1c69aa3 100644 --- a/_drgn.pyi +++ b/_drgn.pyi @@ -203,7 +203,7 @@ class Program: ... def pointer_type( self, - type: Type, + type: Union[str, Type], qualifiers: Optional[Qualifiers] = None, *, language: Optional[Language] = None, @@ -236,6 +236,30 @@ class Program: :raises ValueError: if *size* is negative """ ... + def read_u8(self, address: int, physical: bool = False) -> int: ... + def read_u16(self, address: int, physical: bool = False) -> int: ... + def read_u32(self, address: int, physical: bool = False) -> int: ... + def read_u64(self, address: int, physical: bool = False) -> int: ... + def read_word(self, address: int, physical: bool = False) -> int: + """ + Read an unsigned integer from the program's memory in the program's + byte order. + + :meth:`read_u8()`, :meth:`read_u16()`, :meth:`read_u32()`, and + :meth:`read_u64()` read an 8-, 16-, 32-, or 64-bit unsigned integer, + respectively. :meth:`read_word()` reads a program word-sized unsigned + integer. + + For signed integers, alternate byte order, or other formats, you can + use :meth:`read()` and :meth:`int.from_bytes()` or the :mod:`struct` + module. + + :param address: Address of the integer. + :param physical: Whether *address* is a physical memory address; see + :meth:`read()`. + :raises FaultError: if the address is invalid; see :meth:`read()` + """ + ... def add_memory_segment( self, address: int, @@ -665,7 +689,7 @@ class Object: """ Size in bits of this object if it is a bit field, ``None`` if it is not. """ - def __getattribute__(self, name: str) -> Any: + def __getattribute__(self, name: str) -> Object: """ Implement ``self.name``. @@ -679,7 +703,7 @@ class Object: :param name: Attribute name. """ ... - def __getitem__(self, idx: int) -> Object: + def __getitem__(self, idx: Union[int, Object]) -> Object: """ Implement ``self[idx]``. Get the array element at the given index. @@ -961,7 +985,6 @@ def container_of(ptr: Object, type: Union[str, Type], member: str) -> Object: :param ptr: The pointer. :param type: The type of the containing object. - :type type: str or Type :param member: The name of the member in ``type``. :raises TypeError: if the object is not a pointer or the type is not a structure, union, or class type @@ -1027,13 +1050,20 @@ class StackFrame: pc: int """ - The return address at this stack frame, i.e., the value of the program - counter when control returns to this frame. + The program counter at this stack frame. + + For the innermost frame, this is typically the instruction that was being + executed when the stack trace was captured. For function calls, this is + generally the return address, i.e., the value of the program counter when + control returns to this frame. """ def symbol(self) -> Symbol: """ - Get the function symbol at this stack frame. This is equivalent to - :meth:`prog.symbol(frame.pc) `. + Get the function symbol at this stack frame. + + This may differ from :meth:`prog.symbol(frame.pc) `, as + for function calls, the program counter may be adjusted to the call + instruction instead of the return address. """ ... def register(self, reg: Union[str, int, Register]) -> int: @@ -1603,3 +1633,14 @@ class OutOfBoundsError(Exception): """ ... + +_with_libkdumpfile: bool + +def _linux_helper_read_vm(prog, pgtable, address, size): ... +def _linux_helper_radix_tree_lookup(root, index): ... +def _linux_helper_idr_find(idr, id): ... +def _linux_helper_find_pid(ns, pid): ... +def _linux_helper_pid_task(pid, pid_type): ... +def _linux_helper_find_task(ns, pid): ... +def _linux_helper_task_state_to_char(task): ... +def _linux_helper_pgtable_l5_enabled(prog): ... diff --git a/debian/rules b/debian/rules index 641186e52..a0c591768 100755 --- a/debian/rules +++ b/debian/rules @@ -2,3 +2,17 @@ %: dh $@ --with python3 --buildsystem=pybuild + +override_dh_auto_test: + # + # Don't run drgn's tests during the build step; The repo comes + # with its own testing that takes place elsewhere -> + # https://travis-ci.org/github/delphix/drgn/branches + # + # Ideally it wouldn't hurt having them run here too but due to + # drgn's testing setup, we'd have to override pybuild's default + # behavior. Since drgn is not a project that is owned by us, + # disabling tests here makes even more sense as we won't have + # to adjust the setup here every time a change in the test + # framework of drgn is applied upstream. + # diff --git a/docs/advanced_usage.rst b/docs/advanced_usage.rst index 64ef14875..bc09c6fe4 100644 --- a/docs/advanced_usage.rst +++ b/docs/advanced_usage.rst @@ -94,4 +94,4 @@ Some of drgn's behavior can be modified through environment variables: ``DRGN_USE_LIBKDUMPFILE_FOR_ELF`` Whether drgn should use libkdumpfile for ELF vmcores (0 or 1). The default - is 1 if drgn was built with libkdumpfile support. + is 0. This functionality will be removed in the future. diff --git a/docs/exts/drgndoc/format.py b/docs/exts/drgndoc/format.py index f8121a33f..fb7e6fa2d 100644 --- a/docs/exts/drgndoc/format.py +++ b/docs/exts/drgndoc/format.py @@ -266,6 +266,9 @@ def _add_function_info( node = resolved.node if rst: + if node.docstring is None: + want_rtype = False + params_need_type = set() params_have_type = set() for line in lines: diff --git a/docs/exts/drgndoc/parse.py b/docs/exts/drgndoc/parse.py index 460d2307a..72436919f 100644 --- a/docs/exts/drgndoc/parse.py +++ b/docs/exts/drgndoc/parse.py @@ -3,6 +3,7 @@ import ast import inspect +import operator import os.path import stat from typing import ( @@ -312,11 +313,11 @@ def parse_package( attrs = cast(Dict[str, Node], result[1]) try: - it = os.scandir(path) + entries = sorted(os.scandir(path), key=operator.attrgetter("name")) except OSError as e: handle_err(e) else: - for entry in it: + for entry in entries: try: is_dir = entry.is_dir() is_file = entry.is_file() diff --git a/docs/user_guide.rst b/docs/user_guide.rst index 67c7c7f86..9bd9c8895 100644 --- a/docs/user_guide.rst +++ b/docs/user_guide.rst @@ -299,4 +299,5 @@ Next Steps Refer to the :doc:`api_reference`. Look through the :doc:`helpers`. Browse through the official `examples -`_. +`_ and `tools +`_. diff --git a/drgn/__init__.py b/drgn/__init__.py index fb9bb53cc..7bf30ba2e 100644 --- a/drgn/__init__.py +++ b/drgn/__init__.py @@ -230,13 +230,13 @@ def task_state_to_char(task): sys.argv.extend(args) with _open_code(path) as f: - code = pkgutil.read_code(f) + code = pkgutil.read_code(f) # type: ignore[attr-defined] if code is None: with _open_code(path) as f: code = compile(f.read(), path, "exec") module.__spec__ = None module.__file__ = path - module.__cached__ = None + module.__cached__ = None # type: ignore[attr-defined] caller_globals = sys._getframe(1).f_globals caller_special_globals = { diff --git a/drgn/helpers/__init__.py b/drgn/helpers/__init__.py index 075a67294..3321a868f 100644 --- a/drgn/helpers/__init__.py +++ b/drgn/helpers/__init__.py @@ -22,7 +22,8 @@ """ import enum -from typing import Container, Iterable +import typing +from typing import Container, Iterable, List, Tuple from drgn import Type @@ -98,20 +99,21 @@ def escape_ascii_string( def enum_type_to_class( type: Type, name: str, exclude: Container[str] = (), prefix: str = "" -) -> enum.IntEnum: +) -> typing.Type[enum.IntEnum]: """ Get an :class:`enum.IntEnum` class from an enumerated :class:`drgn.Type`. :param type: The enumerated type to convert. - :type type: :class:`drgn.Type` :param name: The name of the ``IntEnum`` type to create. :param exclude: Container (e.g., list or set) of enumerator names to exclude from the created ``IntEnum``. :param prefix: Prefix to strip from the beginning of enumerator names. """ + if type.enumerators is None: + raise TypeError("enum type is incomplete") enumerators = [ (name[len(prefix) :] if name.startswith(prefix) else name, value) for (name, value) in type.enumerators if name not in exclude ] - return enum.IntEnum(name, enumerators) + return enum.IntEnum(name, enumerators) # type: ignore # python/mypy#4865 diff --git a/drgn/helpers/linux/__init__.py b/drgn/helpers/linux/__init__.py index a0f611683..d8715ce93 100644 --- a/drgn/helpers/linux/__init__.py +++ b/drgn/helpers/linux/__init__.py @@ -35,8 +35,12 @@ __all__ = [] -for _module_info in pkgutil.iter_modules(__path__, prefix=__name__ + "."): +for _module_info in pkgutil.iter_modules( + __path__, # type: ignore[name-defined] # python/mypy#1422 + prefix=__name__ + ".", +): _submodule = importlib.import_module(_module_info.name) - __all__.extend(_submodule.__all__) - for _name in _submodule.__all__: + _submodule_all = getattr(_submodule, "__all__", ()) + __all__.extend(_submodule_all) + for _name in _submodule_all: globals()[_name] = getattr(_submodule, _name) diff --git a/drgn/helpers/linux/kconfig.py b/drgn/helpers/linux/kconfig.py index 14ddea786..406152297 100644 --- a/drgn/helpers/linux/kconfig.py +++ b/drgn/helpers/linux/kconfig.py @@ -52,15 +52,15 @@ def get_kconfig(prog) -> Mapping[str, str]: size = len(kernel_config_data) - 17 data = prog.read(start, size) - result = {} + kconfig = {} for line in gzip.decompress(data).decode().splitlines(): if not line or line.startswith("#"): continue name, _, value = line.partition("=") if value: - result[name] = value + kconfig[name] = value # Make result mapping 'immutable', so changes cannot propagate to the cache - result = types.MappingProxyType(result) + result = types.MappingProxyType(kconfig) prog.cache["kconfig_map"] = result return result diff --git a/drgn/helpers/linux/mm.py b/drgn/helpers/linux/mm.py index 01512346b..78f64fc65 100644 --- a/drgn/helpers/linux/mm.py +++ b/drgn/helpers/linux/mm.py @@ -1,4 +1,4 @@ -# Copyright 2018-2019 - Omar Sandoval +# Copyright 2018-2020 - Omar Sandoval # SPDX-License-Identifier: GPL-3.0+ """ @@ -10,36 +10,35 @@ implemented. """ +from typing import List + +from _drgn import _linux_helper_read_vm, _linux_helper_pgtable_l5_enabled from drgn import Object, cast __all__ = ( + "access_process_vm", + "access_remote_vm", + "cmdline", + "environ", "for_each_page", "page_to_pfn", "page_to_virt", "pfn_to_page", "pfn_to_virt", + "pgtable_l5_enabled", "virt_to_page", "virt_to_pfn", ) -def _vmemmap(prog): - try: - # KASAN - return cast("struct page *", prog["vmemmap_base"]) - except KeyError: - # x86-64 - return Object(prog, "struct page *", value=0xFFFFEA0000000000) - +def pgtable_l5_enabled(prog): + """ + .. c:function:: bool pgtable_l5_enabled(void) -def _page_offset(prog): - try: - # KASAN - return prog["page_offset_base"].value_() - except KeyError: - # x86-64 - return 0xFFFF880000000000 + Return whether 5-level paging is enabled. + """ + return _linux_helper_pgtable_l5_enabled(prog) def for_each_page(prog): @@ -48,7 +47,7 @@ def for_each_page(prog): :return: Iterator of ``struct page *`` objects. """ - vmemmap = _vmemmap(prog) + vmemmap = prog["vmemmap"] for i in range(prog["max_pfn"]): yield vmemmap + i @@ -59,7 +58,7 @@ def page_to_pfn(page): Get the page frame number (PFN) of a page. """ - return cast("unsigned long", page - _vmemmap(page.prog_)) + return cast("unsigned long", page - page.prog_["vmemmap"]) def pfn_to_page(prog_or_pfn, pfn=None): @@ -74,7 +73,7 @@ def pfn_to_page(prog_or_pfn, pfn=None): pfn = prog_or_pfn else: prog = prog_or_pfn - return _vmemmap(prog) + pfn + return prog["vmemmap"] + pfn def virt_to_pfn(prog_or_addr, addr=None): @@ -90,7 +89,7 @@ def virt_to_pfn(prog_or_addr, addr=None): addr = prog_or_addr.value_() else: prog = prog_or_addr - return Object(prog, "unsigned long", value=(addr - _page_offset(prog)) >> 12) + return Object(prog, "unsigned long", value=(addr - prog["PAGE_OFFSET"]) >> 12) def pfn_to_virt(prog_or_pfn, pfn=None): @@ -106,7 +105,7 @@ def pfn_to_virt(prog_or_pfn, pfn=None): pfn = prog_or_pfn.value_() else: prog = prog_or_pfn - return Object(prog, "void *", value=(pfn << 12) + _page_offset(prog)) + return Object(prog, "void *", value=(pfn << 12) + prog["PAGE_OFFSET"]) def page_to_virt(page): @@ -127,3 +126,69 @@ def virt_to_page(prog_or_addr, addr=None): an ``int``. """ return pfn_to_page(virt_to_pfn(prog_or_addr, addr)) + + +def access_process_vm(task, address, size) -> bytes: + """ + .. c:function:: char *access_process_vm(struct task_struct *task, void *address, size_t size) + + Read memory from a task's virtual address space. + + >>> task = find_task(prog, 1490152) + >>> access_process_vm(task, 0x7f8a62b56da0, 12) + b'hello, world' + """ + return _linux_helper_read_vm(task.prog_, task.mm.pgd, address, size) + + +def access_remote_vm(mm, address, size) -> bytes: + """ + .. c:function:: char *access_remote_vm(struct mm_struct *mm, void *address, size_t size) + + Read memory from a virtual address space. This is similar to + :func:`access_process_vm()`, but it takes a ``struct mm_struct *`` instead + of a ``struct task_struct *``. + + >>> task = find_task(prog, 1490152) + >>> access_remote_vm(task.mm, 0x7f8a62b56da0, 12) + b'hello, world' + """ + return _linux_helper_read_vm(mm.prog_, mm.pgd, address, size) + + +def cmdline(task) -> List[bytes]: + """ + Get the list of command line arguments of a task. + + >>> cmdline(find_task(prog, 1495216)) + [b'vim', b'drgn/helpers/linux/mm.py'] + + .. code-block:: console + + $ tr '\\0' ' ' < /proc/1495216/cmdline + vim drgn/helpers/linux/mm.py + """ + mm = task.mm.read_() + arg_start = mm.arg_start.value_() + arg_end = mm.arg_end.value_() + return access_remote_vm(mm, arg_start, arg_end - arg_start).split(b"\0")[:-1] + + +def environ(task) -> List[bytes]: + """ + Get the list of environment variables of a task. + + >>> environ(find_task(prog, 1497797)) + [b'HOME=/root', b'PATH=/usr/local/sbin:/usr/local/bin:/usr/bin', b'LOGNAME=root'] + + .. code-block:: console + + $ tr '\\0' '\\n' < /proc/1497797/environ + HOME=/root + PATH=/usr/local/sbin:/usr/local/bin:/usr/bin + LOGNAME=root + """ + mm = task.mm.read_() + env_start = mm.env_start.value_() + env_end = mm.env_end.value_() + return access_remote_vm(mm, env_start, env_end - env_start).split(b"\0")[:-1] diff --git a/drgn/internal/cli.py b/drgn/internal/cli.py index 8766aa8f6..3c8fd9d07 100644 --- a/drgn/internal/cli.py +++ b/drgn/internal/cli.py @@ -153,13 +153,15 @@ def main() -> None: readline.read_history_file(histfile) except OSError as e: if not isinstance(e, FileNotFoundError) and not args.quiet: - print('could not read history:', str(e), file=sys.stderr) + print("could not read history:", str(e), file=sys.stderr) + def write_history_file(): try: readline.write_history_file(histfile) except OSError as e: if not args.quiet: - print('could not write history:', str(e), file=sys.stderr) + print("could not write history:", str(e), file=sys.stderr) + atexit.register(write_history_file) readline.set_history_length(1000) diff --git a/libdrgn/Makefile.am b/libdrgn/Makefile.am index 83979cad8..0a86f2e28 100644 --- a/libdrgn/Makefile.am +++ b/libdrgn/Makefile.am @@ -60,6 +60,7 @@ libdrgnimpl_la_SOURCES = $(ARCH_INS:.c.in=.c) \ type.h \ type_index.c \ type_index.h \ + util.h \ vector.c \ vector.h @@ -73,10 +74,11 @@ libdrgnimpl_la_LIBADD += $(libkdumpfile_LIBS) endif arch_%.c: arch_%.c.in build-aux/gen_arch.awk build-aux/parse_arch.awk - gawk -f $(word 3, $^) -f $(word 2, $^) $< > $@ + $(AM_V_GEN)gawk -f $(word 3, $^) -f $(word 2, $^) $< > $@ drgn.h: configure.ac build-aux/gen_drgn_h.awk build-aux/parse_arch.awk $(ARCH_INS) drgn.h.in - gawk -f $(word 2, $^) -f $(word 3, $^) -v version=@PACKAGE_VERSION@ \ + $(AM_V_GEN)gawk -f $(word 2, $^) -f $(word 3, $^) \ + -v version=@PACKAGE_VERSION@ \ $(wordlist 4, $(words $^), $^) > $@ elfutils_LIBS = elfutils/libdw/libdw.a elfutils/libelf/libelf.a -lz -llzma -lbz2 @@ -124,16 +126,16 @@ _drgn_la_CFLAGS += $(libkdumpfile_CFLAGS) endif python/constants.c: drgn.h build-aux/gen_constants.py - $(PYTHON) $(word 2, $^) < $< > $@ + $(AM_V_GEN)$(PYTHON) $(word 2, $^) < $< > $@ drgndoc_docstrings_deps = $(wildcard $(srcdir)/../docs/exts/drgndoc/*.py) drgndoc_docstrings = PYTHONPATH="$(srcdir)/../docs/exts:$$PYTHONPATH" $(PYTHON) -m drgndoc.docstrings python/docstrings.c: ../_drgn.pyi $(drgndoc_docstrings_deps) - $(drgndoc_docstrings) -m _drgn:drgn $< > $@ + $(AM_V_GEN)$(drgndoc_docstrings) -m _drgn:drgn $< > $@ python/docstrings.h: ../_drgn.pyi $(drgndoc_docstrings_deps) - $(drgndoc_docstrings) -H -m _drgn:drgn $< > $@ + $(AM_V_GEN)$(drgndoc_docstrings) -H -m _drgn:drgn $< > $@ EXTRA_DIST = $(ARCH_INS) build-aux/gen_arch.awk build-aux/gen_constants.py \ build-aux/gen_drgn_h.awk build-aux/parse_arch.awk diff --git a/libdrgn/arch_x86_64.c.in b/libdrgn/arch_x86_64.c.in index 5c85e882c..e0a41ddd1 100644 --- a/libdrgn/arch_x86_64.c.in +++ b/libdrgn/arch_x86_64.c.in @@ -1,9 +1,13 @@ %{ -// Copyright 2019 - Omar Sandoval +// Copyright 2019-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ +#include + #include "internal.h" +#include "linux_kernel.h" #include "platform.h" +#include "program.h" %} x86-64 @@ -274,11 +278,223 @@ out: return err; } +static struct drgn_error * +linux_kernel_get_page_offset_x86_64(struct drgn_program *prog, uint64_t *ret) +{ + struct drgn_error *err; + struct drgn_object obj; + uint64_t pgd; + + /* + * If KASLR is enabled, PAGE_OFFSET is easily available via + * page_offset_base. + */ + drgn_object_init(&obj, prog); + err = drgn_program_find_object(prog, "page_offset_base", NULL, + DRGN_FIND_OBJECT_VARIABLE, &obj); + if (!err) { + err = drgn_object_read_unsigned(&obj, ret); + goto out; + } + if (err->code == DRGN_ERROR_LOOKUP) + drgn_error_destroy(err); + else + goto out; + + /* + * If not, we determine it based on the kernel page table. Before Linux + * kernel commit d52888aa2753 ("x86/mm: Move LDT remap out of KASLR + * region on 5-level paging") (in v4.20), PAGE_OFFSET was pgd slot 272. + * After that, it is pgd slot 273, and slot 272 is empty (reserved for + * Local Descriptor Table mappings for userspace tasks). + */ + err = drgn_program_read_u64(prog, + prog->vmcoreinfo.swapper_pg_dir + 272 * 8, + false, &pgd); + if (err) + goto out; + if (pgd) { + if (prog->vmcoreinfo.pgtable_l5_enabled) + *ret = UINT64_C(0xff10000000000000); + else + *ret = UINT64_C(0xffff880000000000); + } else { + if (prog->vmcoreinfo.pgtable_l5_enabled) + *ret = UINT64_C(0xff11000000000000); + else + *ret = UINT64_C(0xffff888000000000); + } + +out: + drgn_object_deinit(&obj); + return err; +} + +static struct drgn_error * +linux_kernel_get_vmemmap_x86_64(struct drgn_program *prog, uint64_t *ret) +{ + + struct drgn_error *err; + struct drgn_object obj; + + /* If KASLR is enabled, vmemmap is vmemmap_base. */ + drgn_object_init(&obj, prog); + err = drgn_program_find_object(prog, "vmemmap_base", NULL, + DRGN_FIND_OBJECT_VARIABLE, &obj); + if (!err) { + err = drgn_object_read_unsigned(&obj, ret); + goto out; + } + if (err->code == DRGN_ERROR_LOOKUP) { + drgn_error_destroy(err); + err = NULL; + } else { + goto out; + } + + /* Otherwise, it depends on whether we have 5-level page tables. */ + if (prog->vmcoreinfo.pgtable_l5_enabled) + *ret = UINT64_C(0xffd4000000000000); + else + *ret = UINT64_C(0xffffea0000000000); + +out: + drgn_object_deinit(&obj); + return err; +} + +static struct drgn_error * +linux_kernel_live_direct_mapping_fallback_x86_64(struct drgn_program *prog, + uint64_t *address_ret, + uint64_t *size_ret) +{ + struct drgn_error *err; + unsigned long page_offset_base_address; + + *size_ret = UINT64_C(1) << 46; + err = proc_kallsyms_symbol_addr("page_offset_base", + &page_offset_base_address); + if (!err) { + return drgn_program_read_word(prog, page_offset_base_address, + false, address_ret); + } else if (err == &drgn_not_found) { + /* + * This is only called for pre-4.11 kernels, so we can assume + * the old location. + */ + *address_ret = UINT64_C(0xffff880000000000); + return NULL; + } else { + return err; + } +} + +struct pgtable_iterator_x86_64 { + uint16_t index[5]; + uint64_t table[5][512]; +}; + +static void pgtable_iterator_arch_init_x86_64(void *buf) +{ + struct pgtable_iterator_x86_64 *arch = buf; + memset(arch->index, 0xff, sizeof(arch->index)); + memset(arch->table, 0, sizeof(arch->table)); +} + +static struct drgn_error * +linux_kernel_pgtable_iterator_next_x86_64(struct pgtable_iterator *it, + uint64_t *virt_addr_ret, + uint64_t *phys_addr_ret) +{ + static const int PAGE_SHIFT = 12; + static const int PGTABLE_SHIFT = 9; + static const int PGTABLE_MASK = (1 << PGTABLE_SHIFT) - 1; + static const uint64_t PRESENT = 0x1; + static const uint64_t PSE = 0x80; /* a.k.a. huge page */ + static const uint64_t ADDRESS_MASK = UINT64_C(0xffffffffff000); + struct drgn_program *prog = it->prog; + struct pgtable_iterator_x86_64 *arch = (void *)it->arch; + struct drgn_error *err; + bool bswap = drgn_program_bswap(prog); + int levels = prog->vmcoreinfo.pgtable_l5_enabled ? 5 : 4, level; + + /* Find the lowest level with cached entries. */ + for (level = 0; level < levels; level++) { + if (arch->index[level] < ARRAY_SIZE(arch->table[level])) + break; + } + /* For every level below that, refill the cache/return pages. */ + for (;; level--) { + uint64_t table; + bool table_physical; + uint16_t index; + if (level == levels) { + uint64_t start_non_canonical, end_non_canonical; + start_non_canonical = (UINT64_C(1) << + (PAGE_SHIFT + + PGTABLE_SHIFT * levels - 1)); + end_non_canonical = (UINT64_MAX << + (PAGE_SHIFT + + PGTABLE_SHIFT * levels - 1)); + if (it->virt_addr >= start_non_canonical && + it->virt_addr < end_non_canonical) { + *virt_addr_ret = start_non_canonical; + *phys_addr_ret = UINT64_MAX; + it->virt_addr = end_non_canonical; + return NULL; + } + table = it->pgtable; + table_physical = false; + } else { + uint64_t entry = arch->table[level][arch->index[level]++]; + if (bswap) + entry = bswap_64(entry); + table = entry & ADDRESS_MASK; + if (!(entry & PRESENT) || (entry & PSE) || level == 0) { + uint64_t mask = (UINT64_C(1) << + (PAGE_SHIFT + + PGTABLE_SHIFT * level)) - 1; + *virt_addr_ret = it->virt_addr & ~mask; + if (entry & PRESENT) + *phys_addr_ret = table & ~mask; + else + *phys_addr_ret = UINT64_MAX; + it->virt_addr = (it->virt_addr | mask) + 1; + return NULL; + } + table_physical = true; + } + index = (it->virt_addr >> + (PAGE_SHIFT + PGTABLE_SHIFT * (level - 1))) & PGTABLE_MASK; + /* + * It's only marginally more expensive to read 4096 bytes than 8 + * bytes, so we always read to the end of the table. + */ + err = drgn_program_read_memory(prog, + &arch->table[level - 1][index], + table + 8 * index, + sizeof(arch->table[0]) - 8 * index, + table_physical); + if (err) + return err; + arch->index[level - 1] = index; + } +} + const struct drgn_architecture_info arch_info_x86_64 = { ARCHITECTURE_INFO, .default_flags = (DRGN_PLATFORM_IS_64_BIT | DRGN_PLATFORM_IS_LITTLE_ENDIAN), .frame_registers = frame_registers_x86_64, .num_frame_registers = ARRAY_SIZE(frame_registers_x86_64), - .linux_kernel_set_initial_registers = linux_kernel_set_initial_registers_x86_64, + .linux_kernel_set_initial_registers = + linux_kernel_set_initial_registers_x86_64, + .linux_kernel_get_page_offset = linux_kernel_get_page_offset_x86_64, + .linux_kernel_get_vmemmap = linux_kernel_get_vmemmap_x86_64, + .linux_kernel_live_direct_mapping_fallback = + linux_kernel_live_direct_mapping_fallback_x86_64, + .pgtable_iterator_arch_size = sizeof(struct pgtable_iterator_x86_64), + .pgtable_iterator_arch_init = pgtable_iterator_arch_init_x86_64, + .linux_kernel_pgtable_iterator_next = + linux_kernel_pgtable_iterator_next_x86_64, }; diff --git a/libdrgn/binary_search_tree.h b/libdrgn/binary_search_tree.h index 0752337d9..09f261295 100644 --- a/libdrgn/binary_search_tree.h +++ b/libdrgn/binary_search_tree.h @@ -12,7 +12,7 @@ #ifndef DRGN_BINARY_SEARCH_TREE_H #define DRGN_BINARY_SEARCH_TREE_H -#include "internal.h" +#include "util.h" /** * @ingroup Internals diff --git a/libdrgn/configure.ac b/libdrgn/configure.ac index 075ab3e7d..b4ed56c10 100644 --- a/libdrgn/configure.ac +++ b/libdrgn/configure.ac @@ -1,4 +1,4 @@ -AC_INIT([drgn], [0.0.3], +AC_INIT([drgn], [0.0.4], [https://github.com/osandov/drgn/issues],, [https://github.com/osandov/drgn]) @@ -7,6 +7,7 @@ AC_CONFIG_MACRO_DIR([m4]) AC_PROG_CC AM_INIT_AUTOMAKE([-Wall -Wno-portability foreign subdir-objects]) +AM_SILENT_RULES([yes]) AM_PROG_AR LT_INIT diff --git a/libdrgn/drgn.h.in b/libdrgn/drgn.h.in index c70a2c674..da0596139 100644 --- a/libdrgn/drgn.h.in +++ b/libdrgn/drgn.h.in @@ -446,15 +446,12 @@ struct drgn_type { size_t num_members; struct drgn_type *type; }; + union { + struct drgn_type_member *members; + struct drgn_type_enumerator *enumerators; + struct drgn_type_parameter *parameters; + }; } _private; - /* - * An array of struct drgn_type_member, struct drgn_type_enumerator, or - * struct drgn_type_parameter may follow. We can't use flexible array - * members for these because they are not allowed in a union or nested - * structure; we can't use GCC's zero length array extension because - * that triggers false positives in Clang's AddressSanitizer. Instead, - * these are accessed internally with drgn_type_payload(). - */ }; /** @@ -606,11 +603,6 @@ static inline const char *drgn_type_tag(struct drgn_type *type) return type->_private.tag; } -static inline void *drgn_type_payload(struct drgn_type *type) -{ - return (char *)type + sizeof(*type); -} - /** * Get whether a kind of type has members. This is true for structure, union, * and class types. @@ -633,7 +625,7 @@ static inline bool drgn_type_has_members(struct drgn_type *type) static inline struct drgn_type_member *drgn_type_members(struct drgn_type *type) { assert(drgn_type_has_members(type)); - return drgn_type_payload(type); + return type->_private.members; } /** * Get the number of members of a type. @ref drgn_type_has_members() must be @@ -710,7 +702,7 @@ static inline struct drgn_type_enumerator * drgn_type_enumerators(struct drgn_type *type) { assert(drgn_type_has_enumerators(type)); - return drgn_type_payload(type); + return type->_private.enumerators; } /** * Get the number of enumerators of a type. @ref drgn_type_has_enumerators() @@ -761,7 +753,7 @@ static inline bool drgn_type_has_parameters(struct drgn_type *type) static inline struct drgn_type_parameter *drgn_type_parameters(struct drgn_type *type) { assert(drgn_type_has_parameters(type)); - return drgn_type_payload(type); + return type->_private.parameters; } /** * Get the number of parameters of a type. @ref drgn_type_has_parameters() must @@ -1277,6 +1269,26 @@ struct drgn_error *drgn_program_read_c_string(struct drgn_program *prog, uint64_t address, bool physical, size_t max_size, char **ret); +struct drgn_error *drgn_program_read_u8(struct drgn_program *prog, + uint64_t address, bool physical, + uint8_t *ret); + +struct drgn_error *drgn_program_read_u16(struct drgn_program *prog, + uint64_t address, bool physical, + uint16_t *ret); + +struct drgn_error *drgn_program_read_u32(struct drgn_program *prog, + uint64_t address, bool physical, + uint32_t *ret); + +struct drgn_error *drgn_program_read_u64(struct drgn_program *prog, + uint64_t address, bool physical, + uint64_t *ret); + +struct drgn_error *drgn_program_read_word(struct drgn_program *prog, + uint64_t address, bool physical, + uint64_t *ret); + /** * Find a type in a program by name. * diff --git a/libdrgn/dwarf_index.c b/libdrgn/dwarf_index.c index 51715cdf8..9b0ba5502 100644 --- a/libdrgn/dwarf_index.c +++ b/libdrgn/dwarf_index.c @@ -1298,7 +1298,7 @@ static struct drgn_error *read_module_cus(struct drgn_dwarf_module *module, module->state = DRGN_DWARF_MODULE_INDEXING; return NULL; } - DRGN_UNREACHABLE(); + UNREACHABLE(); } static struct drgn_error *read_cus(struct drgn_dwarf_index *dindex, @@ -1410,7 +1410,8 @@ static struct drgn_error *read_abbrev_decl(const char **ptr, const char *end, break; } - if (should_index || tag == DW_TAG_compile_unit) + if (should_index || tag == DW_TAG_compile_unit || + tag == DW_TAG_partial_unit) die_flags = tag; else die_flags = 0; @@ -1470,7 +1471,8 @@ static struct drgn_error *read_abbrev_decl(const char **ptr, const char *end, break; } } else if (name == DW_AT_stmt_list && - tag == DW_TAG_compile_unit && + (tag == DW_TAG_compile_unit || + tag == DW_TAG_partial_unit) && cu->sections[SECTION_DEBUG_LINE]) { switch (form) { case DW_FORM_data4: @@ -2100,7 +2102,7 @@ static struct drgn_error *index_cu(struct drgn_dwarf_index *dindex, } tag = die.flags & TAG_MASK; - if (tag == DW_TAG_compile_unit) { + if (tag == DW_TAG_compile_unit || tag == DW_TAG_partial_unit) { if (depth == 0 && die.stmt_list != SIZE_MAX && (err = read_file_name_table(dindex, cu, die.stmt_list, diff --git a/libdrgn/dwarf_index.h b/libdrgn/dwarf_index.h index 52843795a..86e6bdc10 100644 --- a/libdrgn/dwarf_index.h +++ b/libdrgn/dwarf_index.h @@ -14,10 +14,19 @@ #include #include -#include #include #include +#ifdef _OPENMP +#include +#else +typedef struct {} omp_lock_t; +#define omp_init_lock(lock) do {} while (0) +#define omp_destroy_lock(lock) do {} while (0) +#define omp_set_lock(lock) do {} while (0) +#define omp_unset_lock(lock) do {} while (0) +#endif + #include "drgn.h" #include "hash_table.h" #include "string_builder.h" diff --git a/libdrgn/dwarf_info_cache.c b/libdrgn/dwarf_info_cache.c index 1be3a80db..1a97a3ef1 100644 --- a/libdrgn/dwarf_info_cache.c +++ b/libdrgn/dwarf_info_cache.c @@ -16,6 +16,9 @@ DEFINE_HASH_TABLE_FUNCTIONS(dwarf_type_map, hash_pair_ptr_type, hash_table_scalar_eq) +DEFINE_VECTOR(drgn_type_member_vector, struct drgn_type_member) +DEFINE_VECTOR(drgn_type_enumerator_vector, struct drgn_type_enumerator) +DEFINE_VECTOR(drgn_type_parameter_vector, struct drgn_type_parameter) struct drgn_type_from_dwarf_thunk { struct drgn_type_thunk thunk; @@ -24,43 +27,33 @@ struct drgn_type_from_dwarf_thunk { bool can_be_incomplete_array; }; -static bool drgn_type_realloc(struct drgn_type **type, size_t capacity, - size_t element_size) -{ - struct drgn_type *tmp; - size_t size; - - if (__builtin_mul_overflow(capacity, element_size, &size) || - __builtin_add_overflow(size, sizeof(**type), &size)) - return false; - - tmp = realloc(*type, size); - if (!tmp) - return false; - - *type = tmp; - return true; -} - static void drgn_dwarf_type_free(struct drgn_dwarf_type *dwarf_type) { if (dwarf_type->should_free) { struct drgn_type *type = dwarf_type->type; if (drgn_type_has_members(type)) { + struct drgn_type_member *members; size_t num_members, i; + members = drgn_type_members(type); num_members = drgn_type_num_members(type); for (i = 0; i < num_members; i++) - drgn_type_member_deinit(type, i); + drgn_type_member_deinit(&members[i]); + free(members); } if (drgn_type_has_parameters(type)) { + struct drgn_type_parameter *parameters; size_t num_parameters, i; + parameters = drgn_type_parameters(type); num_parameters = drgn_type_num_parameters(type); for (i = 0; i < num_parameters; i++) - drgn_type_parameter_deinit(type, i); + drgn_type_parameter_deinit(¶meters[i]); + free(parameters); } + if (drgn_type_has_enumerators(type)) + free(drgn_type_enumerators(type)); free(type); } } @@ -88,24 +81,6 @@ static int dwarf_flag(Dwarf_Die *die, unsigned int name, bool *ret) return dwarf_formflag(attr, ret); } -/** - * Deduce language which corresponds with the CU of the given DIE. - * - * @param[in] die Dwarf_Die used to retrieve the current language. - * @param[out] ret Returned language. - * @return @c NULL on success, non-@c NULL on error. - */ -static struct drgn_error * -drgn_language_from_die(Dwarf_Die *die, const struct drgn_language **ret) -{ - Dwarf_Die cudie; - - if (dwarf_cu_info(die->cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL)) - return drgn_error_libdw(); - *ret = drgn_language_from_dw_lang(dwarf_srclang(&cudie)); - return NULL; -} - /** * Parse a type from a DWARF debugging information entry. * @@ -498,8 +473,9 @@ parse_member_offset(Dwarf_Die *die, struct drgn_lazy_type *member_type, } static struct drgn_error *parse_member(struct drgn_dwarf_info_cache *dicache, - Dwarf_Die *die, struct drgn_type *type, - size_t i, bool little_endian) + Dwarf_Die *die, + struct drgn_type_member *member, + bool little_endian) { struct drgn_error *err; Dwarf_Attribute attr_mem; @@ -545,7 +521,7 @@ static struct drgn_error *parse_member(struct drgn_dwarf_info_cache *dicache, return err; } - drgn_type_member_init(type, i, member_type, name, bit_offset, + drgn_type_member_init(member, member_type, name, bit_offset, bit_field_size); return NULL; } @@ -559,6 +535,7 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, { struct drgn_error *err; struct drgn_type *type; + struct drgn_type_member_vector members; const char *dw_tag_str; uint64_t dw_tag; Dwarf_Attribute attr_mem; @@ -567,7 +544,6 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, bool declaration; Dwarf_Die child; int size; - size_t num_members = 0, capacity = 0; bool little_endian; int r; @@ -585,7 +561,7 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, dw_tag = DW_TAG_class_type; break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } attr = dwarf_attr_integrate(die, DW_AT_name, &attr_mem); @@ -633,12 +609,14 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, drgn_class_type_init_incomplete(type, tag, lang); break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } *ret = type; return NULL; } + drgn_type_member_vector_init(&members); + size = dwarf_bytesize(die); if (size == -1) { err = drgn_error_format(DRGN_ERROR_OTHER, @@ -651,23 +629,19 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, r = dwarf_child(die, &child); while (r == 0) { if (dwarf_tag(&child) == DW_TAG_member) { - if (num_members >= capacity) { - if (capacity == 0) - capacity = 1; - else - capacity *= 2; - if (!drgn_type_realloc(&type, capacity, - sizeof(struct drgn_type_member))) { - err = &drgn_enomem; - goto err; - } - } + struct drgn_type_member *member; - err = parse_member(dicache, &child, type, num_members, + member = drgn_type_member_vector_append_entry(&members); + if (!member) { + err = &drgn_enomem; + goto err; + } + err = parse_member(dicache, &child, member, little_endian); - if (err) + if (err) { + members.size--; goto err; - num_members++; + } } r = dwarf_siblingof(&child, &child); } @@ -676,29 +650,29 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, "libdw could not parse DIE children"); goto err; } - if (capacity != num_members) { - /* We don't care if this fails. */ - drgn_type_realloc(&type, num_members, - sizeof(struct drgn_type_member)); - } + drgn_type_member_vector_shrink_to_fit(&members); if (kind == DRGN_TYPE_UNION) { - drgn_union_type_init(type, tag, size, num_members, lang); + drgn_union_type_init(type, tag, size, members.data, + members.size, lang); } else { - if (kind == DRGN_TYPE_STRUCT) - drgn_struct_type_init(type, tag, size, num_members, lang); - else - drgn_class_type_init(type, tag, size, num_members, lang); + if (kind == DRGN_TYPE_STRUCT) { + drgn_struct_type_init(type, tag, size, members.data, + members.size, lang); + } else { + drgn_class_type_init(type, tag, size, members.data, + members.size, lang); + } /* * Flexible array members are only allowed as the last member of * a structure with more than one named member. We defaulted * can_be_incomplete_array to false in parse_member(), so fix it * up. */ - if (num_members > 1) { + if (members.size > 1) { struct drgn_type_member *member; - member = &drgn_type_members(type)[num_members - 1]; + member = &drgn_type_members(type)[members.size - 1]; /* * The type may have already been evaluated if it's a * bit field. Arrays can't be bit fields, so it's okay @@ -718,15 +692,16 @@ drgn_compound_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, return NULL; err: - while (num_members) - drgn_type_member_deinit(type, --num_members); + for (size_t i = 0; i < members.size; i++) + drgn_type_member_deinit(&members.data[i]); + drgn_type_member_vector_deinit(&members); free(type); return err; } -static struct drgn_error *parse_enumerator(Dwarf_Die *die, - struct drgn_type *type, size_t i, - bool *is_signed) +static struct drgn_error * +parse_enumerator(Dwarf_Die *die, struct drgn_type_enumerator *enumerator, + bool *is_signed) { Dwarf_Attribute attr_mem; Dwarf_Attribute *attr; @@ -751,7 +726,8 @@ static struct drgn_error *parse_enumerator(Dwarf_Die *die, r = dwarf_formsdata(attr, &svalue); if (r == 0) { - drgn_type_enumerator_init_signed(type, i, name, svalue); + drgn_type_enumerator_init_signed(enumerator, name, + svalue); if (svalue < 0) *is_signed = true; } @@ -760,7 +736,7 @@ static struct drgn_error *parse_enumerator(Dwarf_Die *die, r = dwarf_formudata(attr, &uvalue); if (r == 0) { - drgn_type_enumerator_init_unsigned(type, i, name, + drgn_type_enumerator_init_unsigned(enumerator, name, uvalue); } } @@ -838,13 +814,13 @@ drgn_enum_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, Dwarf_Die *die, { struct drgn_error *err; struct drgn_type *type; + struct drgn_type_enumerator_vector enumerators; struct drgn_type *compatible_type; Dwarf_Attribute attr_mem; Dwarf_Attribute *attr; const char *tag; bool declaration; Dwarf_Die child; - size_t num_enumerators = 0, capacity = 0; bool is_signed = false; int r; @@ -885,29 +861,24 @@ drgn_enum_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, Dwarf_Die *die, return NULL; } + drgn_type_enumerator_vector_init(&enumerators); + r = dwarf_child(die, &child); while (r == 0) { int tag; tag = dwarf_tag(&child); if (tag == DW_TAG_enumerator) { - if (num_enumerators >= capacity) { - if (capacity == 0) - capacity = 1; - else - capacity *= 2; - if (!drgn_type_realloc(&type, capacity, - sizeof(struct drgn_type_enumerator))) { - err = &drgn_enomem; - goto err; - } - } + struct drgn_type_enumerator *enumerator; - err = parse_enumerator(&child, type, num_enumerators, - &is_signed); + enumerator = drgn_type_enumerator_vector_append_entry(&enumerators); + if (!enumerator) { + err = &drgn_enomem; + goto err; + } + err = parse_enumerator(&child, enumerator, &is_signed); if (err) goto err; - num_enumerators++; } r = dwarf_siblingof(&child, &child); } @@ -916,11 +887,7 @@ drgn_enum_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, Dwarf_Die *die, "libdw could not parse DIE children"); goto err; } - if (capacity != num_enumerators) { - /* We don't care if this fails. */ - drgn_type_realloc(&type, num_enumerators, - sizeof(struct drgn_type_enumerator)); - } + drgn_type_enumerator_vector_shrink_to_fit(&enumerators); r = dwarf_type(die, &child); if (r == -1) { @@ -947,11 +914,13 @@ drgn_enum_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, Dwarf_Die *die, } } - drgn_enum_type_init(type, tag, compatible_type, num_enumerators, lang); + drgn_enum_type_init(type, tag, compatible_type, enumerators.data, + enumerators.size, lang); *ret = type; return NULL; err: + drgn_type_enumerator_vector_deinit(&enumerators); free(type); return err; } @@ -979,8 +948,10 @@ drgn_typedef_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, if (!type) return &drgn_enomem; - err = drgn_type_from_dwarf_child(dicache, die, lang, "DW_TAG_typedef", - true, can_be_incomplete_array, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), + "DW_TAG_typedef", true, + can_be_incomplete_array, is_incomplete_array_ret, &aliased_type); if (err) { @@ -1001,7 +972,8 @@ drgn_pointer_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, struct drgn_error *err; struct drgn_qualified_type referenced_type; - err = drgn_type_from_dwarf_child(dicache, die, lang, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), "DW_TAG_pointer_type", true, true, NULL, &referenced_type); if (err) @@ -1103,7 +1075,8 @@ drgn_array_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, dimension->is_complete = false; } - err = drgn_type_from_dwarf_child(dicache, die, lang, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), "DW_TAG_array_type", false, false, NULL, &element_type); if (err) @@ -1143,7 +1116,7 @@ drgn_array_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, static struct drgn_error * parse_formal_parameter(struct drgn_dwarf_info_cache *dicache, Dwarf_Die *die, - struct drgn_type *type, size_t i) + struct drgn_type_parameter *parameter) { struct drgn_error *err; Dwarf_Attribute attr_mem; @@ -1168,7 +1141,7 @@ parse_formal_parameter(struct drgn_dwarf_info_cache *dicache, Dwarf_Die *die, if (err) return err; - drgn_type_parameter_init(type, i, parameter_type, name); + drgn_type_parameter_init(parameter, parameter_type, name); return NULL; } @@ -1180,9 +1153,9 @@ drgn_function_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, struct drgn_error *err; const char *tag_name; struct drgn_type *type; + struct drgn_type_parameter_vector parameters; struct drgn_qualified_type return_type; Dwarf_Die child; - size_t num_parameters = 0, capacity = 0; bool is_variadic = false; int r; @@ -1195,12 +1168,16 @@ drgn_function_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, if (!type) return &drgn_enomem; + drgn_type_parameter_vector_init(¶meters); + r = dwarf_child(die, &child); while (r == 0) { int tag; tag = dwarf_tag(&child); if (tag == DW_TAG_formal_parameter) { + struct drgn_type_parameter *parameter; + if (is_variadic) { err = drgn_error_format(DRGN_ERROR_OTHER, "%s has DW_TAG_formal_parameter child after DW_TAG_unspecified_parameters child", @@ -1208,23 +1185,16 @@ drgn_function_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, goto err; } - if (num_parameters >= capacity) { - if (capacity == 0) - capacity = 1; - else - capacity *= 2; - if (!drgn_type_realloc(&type, capacity, - sizeof(struct drgn_type_parameter))) { - err = &drgn_enomem; - goto err; - } + parameter = drgn_type_parameter_vector_append_entry(¶meters); + if (!parameter) { + err = &drgn_enomem; + goto err; } - - err = parse_formal_parameter(dicache, &child, type, - num_parameters); - if (err) + err = parse_formal_parameter(dicache, &child, parameter); + if (err) { + parameters.size--; goto err; - num_parameters++; + } } else if (tag == DW_TAG_unspecified_parameters) { if (is_variadic) { err = drgn_error_format(DRGN_ERROR_OTHER, @@ -1241,25 +1211,24 @@ drgn_function_type_from_dwarf(struct drgn_dwarf_info_cache *dicache, "libdw could not parse DIE children"); goto err; } - if (capacity != num_parameters) { - /* We don't care if this fails. */ - drgn_type_realloc(&type, num_parameters, - sizeof(struct drgn_type_parameter)); - } + drgn_type_parameter_vector_shrink_to_fit(¶meters); - err = drgn_type_from_dwarf_child(dicache, die, lang, tag_name, true, - true, NULL, &return_type); + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), + tag_name, true, true, NULL, + &return_type); if (err) goto err; - drgn_function_type_init(type, return_type, num_parameters, is_variadic, - lang); + drgn_function_type_init(type, return_type, parameters.data, + parameters.size, is_variadic, lang); *ret = type; return NULL; err: - while (num_parameters) - drgn_type_parameter_deinit(type, --num_parameters); + for (size_t i = 0; i < parameters.size; i++) + drgn_type_parameter_deinit(¶meters.data[i]); + drgn_type_parameter_vector_deinit(¶meters); free(type); return err; } @@ -1313,28 +1282,32 @@ drgn_type_from_dwarf_internal(struct drgn_dwarf_info_cache *dicache, * unqualified type. */ entry.value.should_free = false; - err = drgn_type_from_dwarf_child(dicache, die, lang, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), "DW_TAG_const_type", true, true, NULL, ret); ret->qualifiers |= DRGN_QUALIFIER_CONST; break; case DW_TAG_restrict_type: entry.value.should_free = false; - err = drgn_type_from_dwarf_child(dicache, die, lang, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), "DW_TAG_restrict_type", true, true, NULL, ret); ret->qualifiers |= DRGN_QUALIFIER_RESTRICT; break; case DW_TAG_volatile_type: entry.value.should_free = false; - err = drgn_type_from_dwarf_child(dicache, die, lang, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), "DW_TAG_volatile_type", true, true, NULL, ret); ret->qualifiers |= DRGN_QUALIFIER_VOLATILE; break; case DW_TAG_atomic_type: entry.value.should_free = false; - err = drgn_type_from_dwarf_child(dicache, die, lang, + err = drgn_type_from_dwarf_child(dicache, die, + drgn_language_or_default(lang), "DW_TAG_atomic_type", true, true, NULL, ret); ret->qualifiers |= DRGN_QUALIFIER_ATOMIC; @@ -1447,7 +1420,7 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind, tag = DW_TAG_typedef; break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } drgn_dwarf_index_iterator_init(&it, &dicache->dindex, name, name_len, @@ -1498,7 +1471,7 @@ drgn_object_from_dwarf_enumerator(struct drgn_dwarf_info_cache *dicache, 0); } } - DRGN_UNREACHABLE(); + UNREACHABLE(); } static struct drgn_error * @@ -1592,7 +1565,7 @@ drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename, return drgn_object_from_dwarf_variable(dicache, &die, bias, name, ret); default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } if (err && err->code != DRGN_ERROR_STOP) diff --git a/libdrgn/elfutils/CONTRIBUTING b/libdrgn/elfutils/CONTRIBUTING index e3d5a0f78..bb48975ba 100644 --- a/libdrgn/elfutils/CONTRIBUTING +++ b/libdrgn/elfutils/CONTRIBUTING @@ -8,7 +8,7 @@ elfutils-devel@sourceware.org. https://sourceware.org/ml/elfutils-devel/ To subscribe send an email to elfutils-devel-subscribe@sourceware.org -Or use the form at https://sourceware.org/lists.html#ml-requestor +Or use the form at https://sourceware.org/mailman/listinfo/elfutils-devel Please supply patches using git format-patch or using git send-email. diff --git a/libdrgn/elfutils/ChangeLog b/libdrgn/elfutils/ChangeLog index 96d61403e..854568e0b 100644 --- a/libdrgn/elfutils/ChangeLog +++ b/libdrgn/elfutils/ChangeLog @@ -1,3 +1,13 @@ +2020-03-30 Mark Wielaard + + * configure.ac: Set version to 0.179. + * NEWS: Add 0.179 section. + +2020-03-25 Mark Wielaard + + * README: Update mailinglist subscription info. + * CONTRIBUTING: Likewise. + 2020-02-03 Frank Ch. Eigler * configure.ac: Tolerate CXX= for debuginfod configuration. diff --git a/libdrgn/elfutils/NEWS b/libdrgn/elfutils/NEWS index c147ad3cf..d26dccec6 100644 --- a/libdrgn/elfutils/NEWS +++ b/libdrgn/elfutils/NEWS @@ -1,3 +1,38 @@ +Version 0.179 + +debuginfod-client: When DEBUGINFOD_PROGRESS is set and the program doesn't + install its own debuginfod_progressfn_t show download + progress on stderr. + DEBUGINFOD_TIMEOUT is now defined as seconds to get at + least 100K, defaults to 90 seconds. + Default to $XDG_CACHE_HOME/debuginfod_client. + New functions debuginfod_set_user_data, + debuginfod_get_user_data, debuginfod_get_url and + debuginfod_add_http_header. + Support for file:// URLs. + +debuginfod: Uses libarchive directly for reading rpm archives. + Support for indexing .deb/.ddeb archives through dpkg-deb + or bsdtar. + Generic archive support through -Z EXT[=CMD]. Which can be + used for example for arch-linux pacman files by using + -Z '.tar.zst=zstdcat'. + Better logging using User-Agent and X-Forwarded-For headers. + More prometheus metrics. + Support for eliding dots or extraneous slashes in path names. + +debuginfod-find: Accept /path/names in place of buildid hex. + +libelf: Handle PN_XNUM in elf_getphdrnum before shdr 0 is cached + Ensure zlib resource cleanup on failure. + +libdwfl: dwfl_linux_kernel_find_elf and dwfl_linux_kernel_report_offline + now find and handle a compressed vmlinuz image. + +readelf, elflint: Handle PT_GNU_PROPERTY. + +translations: Updated Ukrainian translation. + Version 0.178 debuginfod: New server, client tool and library to index and fetch diff --git a/libdrgn/elfutils/PATCHES b/libdrgn/elfutils/PATCHES index 6ab2e8105..f7dbbb1ba 100644 --- a/libdrgn/elfutils/PATCHES +++ b/libdrgn/elfutils/PATCHES @@ -1,4 +1,4 @@ -commit ad6dd76bc9e4cbb6f0b608ebe3061be3b3bb7c77 +commit c26c6ddb435d87ceafdd8fb36fa99011119d6e3a Author: Omar Sandoval Date: Mon Oct 7 01:30:35 2019 -0700 @@ -9,23 +9,23 @@ Date: Mon Oct 7 01:30:35 2019 -0700 pieces are in place, add dwfl_frame_eval_expr to provide this feature. diff --git a/libdw/libdw.map b/libdw/libdw.map -index 66ec16106..b2df2ba72 100644 +index 5f5946cb1..b4fa63631 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map -@@ -377,4 +377,5 @@ ELFUTILS_0.179 { +@@ -377,4 +377,5 @@ ELFUTILS_0.180 { dwfl_frame_module; dwfl_frame_dwarf_frame; dwfl_frame_register; + dwfl_frame_eval_expr; - } ELFUTILS_0.178; + } ELFUTILS_0.177; diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index 6bf1a3907..13bff8fc6 100644 +index 3984c65ce..4885caa13 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c -@@ -802,3 +802,14 @@ out: - *bias = state->bias; +@@ -814,3 +814,14 @@ out: return state->frame; } + INTDEF (dwfl_frame_dwarf_frame) + +bool +dwfl_frame_eval_expr (Dwfl_Frame *state, const Dwarf_Op *ops, size_t nops, @@ -54,7 +54,7 @@ index fb261698e..1dc080c01 100644 #ifdef __cplusplus } #endif -commit 2f67d8a89d24820bd74f25c0d08bf05cb2c49b81 +commit b32da5a9a88543f144afd50a213afe6fe1d9b25d Author: Omar Sandoval Date: Thu Feb 20 11:44:38 2020 -0800 @@ -63,17 +63,17 @@ Date: Thu Feb 20 11:44:38 2020 -0800 This is useful for debuggers that want to dump register values. diff --git a/libdw/libdw.map b/libdw/libdw.map -index e5def9a54..66ec16106 100644 +index e0fe21156..5f5946cb1 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map -@@ -376,4 +376,5 @@ ELFUTILS_0.179 { +@@ -376,4 +376,5 @@ ELFUTILS_0.180 { dwfl_detach_thread; dwfl_frame_module; dwfl_frame_dwarf_frame; + dwfl_frame_register; - } ELFUTILS_0.178; + } ELFUTILS_0.177; diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index 480636718..6bf1a3907 100644 +index 9ada2e550..3984c65ce 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -44,8 +44,7 @@ @@ -86,7 +86,15 @@ index 480636718..6bf1a3907 100644 { Ebl *ebl = state->thread->process->ebl; if (! ebl_dwarf_to_regno (ebl, ®no)) -@@ -81,7 +80,7 @@ __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) +@@ -59,6 +58,7 @@ __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) + *val = state->regs[regno]; + return true; + } ++INTDEF (dwfl_frame_register) + + bool + internal_function +@@ -81,7 +81,7 @@ __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val) static bool state_get_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) { @@ -95,7 +103,7 @@ index 480636718..6bf1a3907 100644 { __libdwfl_seterrno (DWFL_E_INVALID_REGISTER); return false; -@@ -625,9 +624,9 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Frame *frame, Dwarf_Addr bias) +@@ -628,9 +628,9 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Frame *frame, Dwarf_Addr bias) } if (unwound->pc_state == DWFL_FRAME_STATE_ERROR) { @@ -108,7 +116,7 @@ index 480636718..6bf1a3907 100644 { /* PPC32 __libc_start_main properly CFI-unwinds PC as zero. Currently none of the archs supported for unwinding have -@@ -684,7 +683,7 @@ getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) +@@ -687,7 +687,7 @@ getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) Dwfl_Frame *state = arg; assert (firstreg >= 0); while (nregs--) @@ -134,10 +142,10 @@ index b494d4582..fb261698e 100644 } #endif diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h -index 659e671a6..eab003e66 100644 +index 90d509ece..613ccf016 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h -@@ -284,12 +284,6 @@ struct Dwfl_Frame +@@ -283,12 +283,6 @@ struct Dwfl_Frame Dwarf_Addr regs[]; }; @@ -150,6 +158,14 @@ index 659e671a6..eab003e66 100644 /* Store value to Dwfl_Frame->regs indexed by DWARF REGNO. No error code is set if the function returns FALSE. */ bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, +@@ -788,6 +782,7 @@ INTDECL (dwfl_getthread_frames) + INTDECL (dwfl_getthreads) + INTDECL (dwfl_thread_getframes) + INTDECL (dwfl_frame_pc) ++INTDECL (dwfl_frame_register) + + /* Leading arguments standard to callbacks passed a Dwfl_Module. */ + #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c index c0f1b0d00..d55312b6c 100644 --- a/libdwfl/linux-core-attach.c @@ -167,7 +183,7 @@ index c0f1b0d00..d55312b6c 100644 continue; Dwarf_Word val; switch (regloc->bits) -commit e289ead84e610640d086d44eb3d1149781b0f971 +commit 1426c2a70c1748cd5a6f4e38410ae4e9796d3037 Author: Omar Sandoval Date: Thu Feb 20 11:18:28 2020 -0800 @@ -183,18 +199,18 @@ Date: Thu Feb 20 11:18:28 2020 -0800 frame, so add dwfl_frame_module. diff --git a/libdw/libdw.map b/libdw/libdw.map -index 4f3ad91d4..e5def9a54 100644 +index c8961b3a6..e0fe21156 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map -@@ -374,4 +374,6 @@ ELFUTILS_0.179 { +@@ -374,4 +374,6 @@ ELFUTILS_0.180 { global: dwfl_attach_thread; dwfl_detach_thread; + dwfl_frame_module; + dwfl_frame_dwarf_frame; - } ELFUTILS_0.178; + } ELFUTILS_0.177; diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c -index 61fad8b9c..80f2bc146 100644 +index 0ad28e0f5..046f6c2ba 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c @@ -68,6 +68,13 @@ state_fetch_pc (Dwfl_Frame *state) @@ -228,10 +244,10 @@ index 61fad8b9c..80f2bc146 100644 + state->frame = NULL; + state->moderr = DWFL_E_NOERROR; + state->frameerr = DWFL_E_NOERROR; - state->signal_frame = false; - state->initial_frame = true; + state->isactivation = true; state->pc_state = DWFL_FRAME_STATE_ERROR; -@@ -486,7 +497,7 @@ dwfl_thread_getframes (Dwfl_Thread *thread, + memset (state->regs_set, 0, sizeof (state->regs_set)); +@@ -485,7 +496,7 @@ dwfl_thread_getframes (Dwfl_Thread *thread, if (! cache) { /* The old frame is no longer needed. */ @@ -241,7 +257,7 @@ index 61fad8b9c..80f2bc146 100644 state = next; } diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c -index d7dfa5a94..480636718 100644 +index df755975e..9ada2e550 100644 --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -523,6 +523,10 @@ new_unwound (Dwfl_Frame *state) @@ -252,10 +268,10 @@ index d7dfa5a94..480636718 100644 + unwound->frame = NULL; + unwound->moderr = DWFL_E_NOERROR; + unwound->frameerr = DWFL_E_NOERROR; - unwound->signal_frame = false; - unwound->initial_frame = false; + unwound->isactivation = false; unwound->pc_state = DWFL_FRAME_STATE_ERROR; -@@ -536,22 +540,9 @@ new_unwound (Dwfl_Frame *state) + memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); +@@ -535,22 +539,9 @@ new_unwound (Dwfl_Frame *state) later. Therefore we continue unwinding leaving the registers undefined. */ static void @@ -277,10 +293,10 @@ index d7dfa5a94..480636718 100644 - } - + Dwfl_Frame *unwound = state->unwound; - unwound->signal_frame = frame->fde->cie->signal_frame; - Dwfl_Thread *thread = state->thread; - Dwfl_Process *process = thread->process; -@@ -665,7 +656,6 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) + if (frame->fde->cie->signal_frame) + { + state->isactivation = true; +@@ -668,7 +659,6 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; } } @@ -289,8 +305,8 @@ index d7dfa5a94..480636718 100644 static bool @@ -724,28 +714,16 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - Then we need to unwind from the original, unadjusted PC. */ - if (! state->initial_frame && ! state->signal_frame) + assert (ok); + if (! isactivation) pc--; - Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); - if (mod == NULL) @@ -325,9 +341,9 @@ index d7dfa5a94..480636718 100644 Dwfl_Thread *thread = state->thread; Dwfl_Process *process = thread->process; Ebl *ebl = process->ebl; -@@ -770,3 +748,58 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) - assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); - state->unwound->signal_frame = signal_frame; +@@ -773,3 +751,66 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) + state->unwound->isactivation = true; + } } + +Dwfl_Module * @@ -338,7 +354,10 @@ index d7dfa5a94..480636718 100644 + if (state->moderr == DWFL_E_NOERROR) + { + Dwarf_Addr pc; -+ INTUSE(dwfl_frame_pc) (state, &pc, NULL); ++ bool isactivation; ++ INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); ++ if (! isactivation) ++ pc--; + state->mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); + if (state->mod != NULL) + return state->mod; @@ -347,6 +366,7 @@ index d7dfa5a94..480636718 100644 + __libdwfl_seterrno (state->moderr); + return NULL; +} ++INTDEF (dwfl_frame_module) + +Dwarf_Frame * +dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) @@ -362,7 +382,10 @@ index d7dfa5a94..480636718 100644 + return NULL; + } + Dwarf_Addr pc; -+ INTUSE(dwfl_frame_pc) (state, &pc, NULL); ++ bool isactivation; ++ INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); ++ if (! isactivation) ++ pc--; + Dwarf_CFI *cfi = INTUSE(dwfl_module_eh_cfi) (state->mod, + &state->bias); + if (cfi @@ -384,6 +407,7 @@ index d7dfa5a94..480636718 100644 + *bias = state->bias; + return state->frame; +} ++INTDEF (dwfl_frame_dwarf_frame) diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h index 4167ef7ad..b494d4582 100644 --- a/libdwfl/libdwfl.h @@ -406,7 +430,7 @@ index 4167ef7ad..b494d4582 100644 For every known continuous block of registers Date: Mon Oct 7 01:22:39 2019 -0700 @@ -441,23 +474,23 @@ Date: Mon Oct 7 01:22:39 2019 -0700 possible to use the frames after dwfl_thread_getframes returns. diff --git a/libdw/libdw.map b/libdw/libdw.map -index decac05c7..4f3ad91d4 100644 +index decac05c7..c8961b3a6 100644 --- a/libdw/libdw.map +++ b/libdw/libdw.map @@ -370,3 +370,8 @@ ELFUTILS_0.177 { # presume that NULL is only returned on error (otherwise ELF_K_NONE). dwelf_elf_begin; } ELFUTILS_0.175; -+ELFUTILS_0.179 { ++ELFUTILS_0.180 { + global: + dwfl_attach_thread; + dwfl_detach_thread; -+} ELFUTILS_0.178; ++} ELFUTILS_0.177; diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c -index 5bbf850e8..61fad8b9c 100644 +index d5043cbbe..0ad28e0f5 100644 --- a/libdwfl/dwfl_frame.c +++ b/libdwfl/dwfl_frame.c -@@ -103,6 +103,29 @@ state_alloc (Dwfl_Thread *thread) +@@ -102,6 +102,29 @@ state_alloc (Dwfl_Thread *thread) return state; } @@ -487,7 +520,7 @@ index 5bbf850e8..61fad8b9c 100644 void internal_function __libdwfl_process_free (Dwfl_Process *process) -@@ -366,6 +389,45 @@ getthread (Dwfl *dwfl, pid_t tid, +@@ -365,6 +388,45 @@ getthread (Dwfl *dwfl, pid_t tid, return err; } @@ -533,7 +566,7 @@ index 5bbf850e8..61fad8b9c 100644 struct one_thread { int (*callback) (Dwfl_Frame *frame, void *arg); -@@ -394,63 +456,55 @@ dwfl_thread_getframes (Dwfl_Thread *thread, +@@ -393,63 +455,55 @@ dwfl_thread_getframes (Dwfl_Thread *thread, int (*callback) (Dwfl_Frame *state, void *arg), void *arg) { @@ -654,7 +687,7 @@ index d5fa06d47..4167ef7ad 100644 have been processed by the callback, returns -1 on error, or the value of the callback when not DWARF_CB_OK. -1 returned on error will diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h -index 25753de2f..bc088861f 100644 +index 332349d32..ed8239c92 100644 --- a/libdwfl/libdwflP.h +++ b/libdwfl/libdwflP.h @@ -239,7 +239,8 @@ struct Dwfl_Thread @@ -667,7 +700,213 @@ index 25753de2f..bc088861f 100644 Dwfl_Frame *unwound; void *callbacks_arg; }; -commit b1515e3863da68aaee2b636121339c225095d8b9 +commit a1f60f2e2794859c7767b0b003efb20e3e018904 +Author: Omar Sandoval +Date: Wed May 13 14:18:12 2020 -0700 + + libdwfl: simplify activation frame logic + + When calling a noreturn function, the compiler may omit any code after + the call instruction. As a result, the return address on the stack may + not lie in the FDE for the caller. It might even lie in another symbol. + In the following example, the return address for the _Exit call in foo + is actually the first instruction of bar. + + 0000000000001149 : + 1149: 50 push %rax + 114a: bf 01 00 00 00 mov $0x1,%edi + 114f: e8 dc fe ff ff callq 1030 <_Exit@plt> + + 0000000000001154 : + 1154: b8 37 13 00 00 mov $0x1337,%eax + 1159: c3 retq + + To handle this, libdwfl (and GDB, for that matter) decrements the + program counter when looking up the debugging information for a frame. + + There are two important exceptions. The first is the initial (i.e., + innermost) frame. This is typically supplied by ptrace or a PRSTATUS + note, which contains the exact trapped PC. libdwfl calls this case an + "activation" and doesn't decrement the PC. + + The second exception is signal handling. When a signal is received, the + kernel creates a special signal stack frame so that when the signal + handler returns, it returns to the signal trampoline code responsible + for resuming execution (see sigreturn(2)). + + The return address from the signal frame is the exact interrupted + instruction. Therefore, the interrupted frame (that is, the outer frame + of a signal frame) is also considered an activation. + + The signal frame itself is also considered an activation frame, since + the return address points directly to the signal trampoline. However, + determining that a frame is a signal frame requires looking up the FDE. + To solve this chicken and egg problem, the signal trampoline is padded + so that the debugger can still find the FDE even if it decrements PC + (see [1]). This means that during the initial lookup, we can assume it's + not an activation, and then fix it up after the fact. + + libdwfl annotates the interrupted frame (NB, not the signal frame) with + Dwfl_Frame::signal_frame. dwfl_frame_pc returns that a frame is an + activation if it is the interrupted frame, or if its outer frame is the + interrupted frame (which means it is the signal frame). This requires + unwinding the frame, so when the unwinding code calls dwfl_frame_pc, it + has to open-code the logic for determining whether the activation frame + check. + + This can all be made a lot simpler by instead directly tracking whether + a Dwfl_Frame is an activation frame. This replaces + Dwfl_Frame::initial_frame and Dwfl_Frame::signal_frame with + Dwfl_Frame::isactivation. We set isactivation to true for the initial + frame, the signal frame, and the interrupted frame. + + 1: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/entry/vdso/vdso32/sigreturn.S?h=v5.6#n54 + +diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c +index 5bbf850e8..d5043cbbe 100644 +--- a/libdwfl/dwfl_frame.c ++++ b/libdwfl/dwfl_frame.c +@@ -94,8 +94,7 @@ state_alloc (Dwfl_Thread *thread) + if (state == NULL) + return NULL; + state->thread = thread; +- state->signal_frame = false; +- state->initial_frame = true; ++ state->isactivation = true; + state->pc_state = DWFL_FRAME_STATE_ERROR; + memset (state->regs_set, 0, sizeof (state->regs_set)); + thread->unwound = state; +diff --git a/libdwfl/dwfl_frame_pc.c b/libdwfl/dwfl_frame_pc.c +index 296c815b9..a955d995a 100644 +--- a/libdwfl/dwfl_frame_pc.c ++++ b/libdwfl/dwfl_frame_pc.c +@@ -39,26 +39,7 @@ dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) + *pc = state->pc; + ebl_normalize_pc (state->thread->process->ebl, pc); + if (isactivation) +- { +- /* Bottom frame? */ +- if (state->initial_frame) +- *isactivation = true; +- /* *ISACTIVATION is logical union of whether current or previous frame +- state is SIGNAL_FRAME. */ +- else if (state->signal_frame) +- *isactivation = true; +- else +- { +- /* If the previous frame has unwound unsuccessfully just silently do +- not consider it could be a SIGNAL_FRAME. */ +- __libdwfl_frame_unwind (state); +- if (state->unwound == NULL +- || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET) +- *isactivation = false; +- else +- *isactivation = state->unwound->signal_frame; +- } +- } ++ *isactivation = state->isactivation; + return true; + } + INTDEF (dwfl_frame_pc) +diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c +index 83b1abef1..d013dc966 100644 +--- a/libdwfl/dwfl_frame_regs.c ++++ b/libdwfl/dwfl_frame_regs.c +@@ -38,7 +38,6 @@ dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg, + { + Dwfl_Frame *state = thread->unwound; + assert (state && state->unwound == NULL); +- assert (state->initial_frame); + for (unsigned regno = firstreg; regno < firstreg + nregs; regno++) + if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg])) + { +@@ -54,7 +53,6 @@ dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) + { + Dwfl_Frame *state = thread->unwound; + assert (state && state->unwound == NULL); +- assert (state->initial_frame); + state->pc = pc; + state->pc_state = DWFL_FRAME_STATE_PC_SET; + } +diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c +index d7dfa5a94..df755975e 100644 +--- a/libdwfl/frame_unwind.c ++++ b/libdwfl/frame_unwind.c +@@ -523,8 +523,7 @@ new_unwound (Dwfl_Frame *state) + state->unwound = unwound; + unwound->thread = thread; + unwound->unwound = NULL; +- unwound->signal_frame = false; +- unwound->initial_frame = false; ++ unwound->isactivation = false; + unwound->pc_state = DWFL_FRAME_STATE_ERROR; + memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); + return unwound; +@@ -552,7 +551,11 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) + return; + } + +- unwound->signal_frame = frame->fde->cie->signal_frame; ++ if (frame->fde->cie->signal_frame) ++ { ++ state->isactivation = true; ++ unwound->isactivation = true; ++ } + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; + Ebl *ebl = process->ebl; +@@ -715,14 +718,11 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) + { + if (state->unwound) + return; +- /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE +- which would deadlock us. */ + Dwarf_Addr pc; +- bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL); ++ bool isactivation; ++ bool ok = INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); + assert (ok); +- /* Check whether this is the initial frame or a signal frame. +- Then we need to unwind from the original, unadjusted PC. */ +- if (! state->initial_frame && ! state->signal_frame) ++ if (! isactivation) + pc--; + Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); + if (mod == NULL) +@@ -755,7 +755,6 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) + return; + } + state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; +- // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. + bool signal_frame = false; + if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) + { +@@ -768,5 +767,9 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) + return; + } + assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); +- state->unwound->signal_frame = signal_frame; ++ if (signal_frame) ++ { ++ state->isactivation = true; ++ state->unwound->isactivation = true; ++ } + } +diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h +index 25753de2f..332349d32 100644 +--- a/libdwfl/libdwflP.h ++++ b/libdwfl/libdwflP.h +@@ -251,8 +251,7 @@ struct Dwfl_Frame + Dwfl_Thread *thread; + /* Previous (outer) frame. */ + Dwfl_Frame *unwound; +- bool signal_frame : 1; +- bool initial_frame : 1; ++ bool isactivation; + enum + { + /* This structure is still being initialized or there was an error +commit 148c39884329b1279c2fc4c63500f95b95205651 Author: Omar Sandoval Date: Wed Sep 4 17:13:40 2019 -0700 @@ -695,7 +934,7 @@ index f4052125b..1beb661eb 100644 modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \ tilegx m68k bpf riscv csky diff --git a/configure.ac b/configure.ac -index f4c5c603f..31d3b6605 100644 +index 12ee2f97c..d68d1a1eb 100644 --- a/configure.ac +++ b/configure.ac @@ -70,6 +70,11 @@ AC_ARG_ENABLE([programs], @@ -711,7 +950,7 @@ index f4c5c603f..31d3b6605 100644 [AS_HELP_STRING([--enable-deterministic-archives], [ar and ranlib default to -D behavior])], [ diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am -index f4756c92f..dcae77d07 100644 +index e62e8d14b..a811e2dd1 100644 --- a/debuginfod/Makefile.am +++ b/debuginfod/Makefile.am @@ -86,16 +86,20 @@ libdebuginfod.so$(EXEEXT): $(srcdir)/libdebuginfod.map $(libdebuginfod_so_LIBS) @@ -900,7 +1139,7 @@ index d5d63f733..94e6e38f6 100644 EXTRA_DIST = libelf.map -commit 844aa1ab3265e5072ab2cc31562946d4da2f9d60 +commit 5ac48d7d9fc93c792e5bb45f91ea2f6f7190617c Author: Omar Sandoval Date: Wed Sep 4 17:13:23 2019 -0700 @@ -928,7 +1167,7 @@ index bd8926b52..0b13c717f 100644 if DEBUGINFOD SUBDIRS += debuginfod diff --git a/configure.ac b/configure.ac -index 14ad66f29..f4c5c603f 100644 +index a39e800f7..12ee2f97c 100644 --- a/configure.ac +++ b/configure.ac @@ -65,6 +65,11 @@ AC_CONFIG_FILES([debuginfod/Makefile]) @@ -944,7 +1183,7 @@ index 14ad66f29..f4c5c603f 100644 [AS_HELP_STRING([--enable-deterministic-archives], [ar and ranlib default to -D behavior])], [ diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am -index 52ead30ae..f4756c92f 100644 +index 51965f65d..e62e8d14b 100644 --- a/debuginfod/Makefile.am +++ b/debuginfod/Makefile.am @@ -57,7 +57,9 @@ libeu = ../lib/libeu.a diff --git a/libdrgn/elfutils/README b/libdrgn/elfutils/README index 0e15bae6b..06a9fcd0d 100644 --- a/libdrgn/elfutils/README +++ b/libdrgn/elfutils/README @@ -24,7 +24,7 @@ elfutils-devel@sourceware.org. https://sourceware.org/ml/elfutils-devel/ To subscribe send an email to elfutils-devel-subscribe@sourceware.org -Or use the form at https://sourceware.org/lists.html#ml-requestor +Or use the form at https://sourceware.org/mailman/listinfo/elfutils-devel See the CONTRIBUTING file for how to propose patches to the code. diff --git a/libdrgn/elfutils/config/ChangeLog b/libdrgn/elfutils/config/ChangeLog index f420dba63..c3b5684af 100644 --- a/libdrgn/elfutils/config/ChangeLog +++ b/libdrgn/elfutils/config/ChangeLog @@ -1,3 +1,25 @@ +2020-04-21 Frank Ch. Eigler + + * debuginfod.sysconfig (DEBUGINFOD_PATHS): Add /var/lib/pulp. + +2020-03-30 Mark Wielaard + + * upload-release.sh: chmod uploaded dir and files to make them + readable. + +2020-03-30 Mark Wielaard + + * elfutils.spec.in: Update for 0.179. + +2020-03-25 Frank Ch. Eigler + + * elfutils.spec.in: *Require: bsdtar instead of dpkg. + +2020-03-04 Mark Wielaard + + * elfutils.spec.in (package debuginfod): Remove Requires: rpm. + Add Requires: dpkg. + 2020-01-12 Frank Ch. Eigler * elfutils.spec.in: Typo fix for "Requires: debuginfod-client". diff --git a/libdrgn/elfutils/config/debuginfod.sysconfig b/libdrgn/elfutils/config/debuginfod.sysconfig index c56bcf3fc..446038742 100644 --- a/libdrgn/elfutils/config/debuginfod.sysconfig +++ b/libdrgn/elfutils/config/debuginfod.sysconfig @@ -3,7 +3,7 @@ DEBUGINFOD_PORT="8002" #DEBUGINFOD_VERBOSE="-v" # some common places to find trustworthy ELF/DWARF files and RPMs -DEBUGINFOD_PATHS="-t43200 -F -R /usr/lib/debug /usr/bin /usr/libexec /usr/sbin /usr/lib /usr/lib64 /var/cache/yum /var/cache/dnf" +DEBUGINFOD_PATHS="-t43200 -F -R /usr/lib/debug /usr/bin /usr/libexec /usr/sbin /usr/lib /usr/lib64 /var/cache/yum /var/cache/dnf /var/lib/pulp" # prefer reliability/durability over performance #DEBUGINFOD_PRAGMAS="-D 'pragma synchronous=full;'" diff --git a/libdrgn/elfutils/config/elfutils.spec.in b/libdrgn/elfutils/config/elfutils.spec.in index e992812a7..9f614882c 100644 --- a/libdrgn/elfutils/config/elfutils.spec.in +++ b/libdrgn/elfutils/config/elfutils.spec.in @@ -35,9 +35,7 @@ BuildRequires: pkgconfig(libarchive) >= 3.1.2 BuildRequires: bzip2 # For the run-debuginfod-find.sh test case in %check for /usr/sbin/ss BuildRequires: iproute -%if 0%{?fedora} >= 20 -BuildRequires: dpkg -%endif +BuildRequires: bsdtar BuildRequires: curl %define _gnu %{nil} @@ -157,8 +155,8 @@ Requires(post): systemd Requires(preun): systemd Requires(postun): systemd Requires(pre): shadow-utils -# For /usr/bin/cpio2rpm -Requires: rpm +# To extract .deb files with a bsdtar (= libarchive) subshell +Requires: bsdtar %description debuginfod-client The elfutils-debuginfod-client package contains shared libraries @@ -329,6 +327,31 @@ exit 0 %systemd_postun_with_restart debuginfod.service %changelog +* Mon Mar 30 2020 Mark Wielaard 0.179-1 +- debuginfod-client: When DEBUGINFOD_PROGRESS is set and the program + doesn't install its own debuginfod_progressfn_t show download + progress on stderr. + DEBUGINFOD_TIMEOUT is now defined as seconds to get at least 100K, + defaults to 90 seconds. + Default to $XDG_CACHE_HOME/debuginfod_client. + New functions debuginfod_set_user_data, debuginfod_get_user_data, + debuginfod_get_url and debuginfod_add_http_header. + Support for file:// URLs. +- debuginfod: Uses libarchive directly for reading rpm archives. + Support for indexing .deb/.ddeb archives through dpkg-deb or bsdtar. + Generic archive support through -Z EXT[=CMD]. Which can be used for + example for arch-linux pacman files by using -Z '.tar.zst=zstdcat'. + Better logging using User-Agent and X-Forwarded-For headers. + More prometheus metrics. + Support for eliding dots or extraneous slashes in path names. +- debuginfod-find: Accept /path/names in place of buildid hex. +- libelf: Handle PN_XNUM in elf_getphdrnum before shdr 0 is cached. + Ensure zlib resource cleanup on failure. +- libdwfl: dwfl_linux_kernel_find_elf and dwfl_linux_kernel_report_offline + now find and handle a compressed vmlinuz image. +- readelf, elflint: Handle PT_GNU_PROPERTY. +- translations: Updated Ukrainian translation. + * Tue Nov 26 2019 Mark Wielaard 0.178-1 - debuginfod: New server, client tool and library to index and fetch ELF/DWARF files addressed by build-id through HTTP. diff --git a/libdrgn/elfutils/config/upload-release.sh b/libdrgn/elfutils/config/upload-release.sh index df5e3a073..b52642ea8 100755 --- a/libdrgn/elfutils/config/upload-release.sh +++ b/libdrgn/elfutils/config/upload-release.sh @@ -50,6 +50,8 @@ cp -r $VERSION $HOME/elfutils-$VERSION # Upload scp -r $VERSION sourceware.org:/sourceware/ftp/pub/elfutils/ ssh sourceware.org "(cd /sourceware/ftp/pub/elfutils \ + && chmod go+rx $VERSION \ + && chmod go+r $VERSION/elfutils-$VERSION.tar.bz2* \ && ln -sf $VERSION/elfutils-$VERSION.tar.bz2 elfutils-latest.tar.bz2 \ && ln -sf $VERSION/elfutils-$VERSION.tar.bz2.sig elfutils-latest.tar.bz2.sig \ && ls -lah elfutils-latest*)" diff --git a/libdrgn/elfutils/configure.ac b/libdrgn/elfutils/configure.ac index 31d3b6605..d68d1a1eb 100644 --- a/libdrgn/elfutils/configure.ac +++ b/libdrgn/elfutils/configure.ac @@ -17,7 +17,7 @@ dnl GNU General Public License for more details. dnl dnl You should have received a copy of the GNU General Public License dnl along with this program. If not, see . -AC_INIT([elfutils],[0.178],[https://sourceware.org/bugzilla],[elfutils],[http://elfutils.org/]) +AC_INIT([elfutils],[0.179],[https://sourceware.org/bugzilla],[elfutils],[http://elfutils.org/]) dnl Workaround for older autoconf < 2.64 m4_ifndef([AC_PACKAGE_URL], diff --git a/libdrgn/elfutils/debuginfod/ChangeLog b/libdrgn/elfutils/debuginfod/ChangeLog index b297a3749..bc3bce32f 100644 --- a/libdrgn/elfutils/debuginfod/ChangeLog +++ b/libdrgn/elfutils/debuginfod/ChangeLog @@ -1,3 +1,144 @@ +2020-03-29 Mark Wielaard + + * debuginfod-client.c (debuginfod_add_http_header): Check header + contains precisely one colon that isn't the first or last char. + +2020-03-29 Frank Ch. Eigler + + * debuginfod-client.c (struct debuginfod_client): Add a flag field + for progressfn printing. + (default_progressfn): Set it if printing \rsomething. + (debuginfod_end): Terminate with \n if flag set, i.e., only if the + default_progressfn was actually called. + +2020-03-27 Mark Wielaard + + * debuginfod.cxx (parse_opt): Check port is not zero. + +2020-03-28 Frank Ch. Eigler + + * debuginfod.cxx (handle_buildid_r_match): During archive + extraction / fdcache prefetching, set the mtime of each + file in the cache. + +2020-03-27 Frank Ch. Eigler + + * debuginfod-find.c (main): Extract buildid from /binary/ if + given instead of hex string. + * Makefile.am: Add elfutils library prereqs for debuginfod-find. + +2020-03-24 Frank Ch. Eigler + + * debuginfod.h, libdebuginfod.map: New functions for _add_url_header. + * debuginfod-client.c (struct debuginfod_client): Add headers fields. + (debuginfod_add_http_header): New client api to add outgoing headers. + (add_default_headers): Renamed from add_extra_headers, skip if flag. + (debuginfod_query_server): Pass accumulated headers to libcurl. + (debuginfod_end): Clean accumulated headers. + (debuginfod_find_*): Add default headers at this point. + * debuginfod.cxx (handle_buildid): Add conn pointer. Use it to relay + incoming UA and XFF headers to federated upstream debuginfods. + +2020-03-26 Frank Ch. Eigler + + * debuginfod.cxx (handler_cb): Export two families of metrics for + prometheus traffic analysis: response times and data amounts. + +2020-03-26 Frank Ch. Eigler + + * debuginfod.cxx (parse_opt): For -U, prefer dpkg-deb + after all if access(3)-able, fallback to bsdtar. + +2020-03-25 Frank Ch. Eigler + + * debuginfod.cxx (parse_opt): Associate a bsdtar subshell with + the .deb & .ddeb extensions, instead of dpkg-deb. + +2020-03-26 Frank Ch. Eigler + + * debuginfod-client.c (debuginfod_query_server): Don't + set CURLOPT_PATH_AS_IS on old curl. Mostly harmless. + +2020-03-24 Frank Ch. Eigler + + * debuginfod-client.c (debuginfod_query_server): Set + CURLOPT_PATH_AS_IS, to propagate file names verbatim. + * debuginfod.cxx (canon_pathname): Implement RFC3986 + style pathname canonicalization. + (handle_buildid): Canonicalize incoming webapi source + paths, accept either one. + (scan_source_file, archive_classify): Store both + original and canonicalized dwarf-source file names. + +2020-03-24 Frank Ch. Eigler + + * debuginfod.cxx (handle_buildid): In case of federated fallback + queries, handle errors analogously to local ENOENT/404. + (handle_metrics): Return a size-of-response value. + (handler_cb): Add code to time entire application-side processing + stage + response sizes + http codes, so as to emit a complete + httpd-flavoured log line for each webapi request. + +2020-03-24 Frank Ch. Eigler + + * debuginfod-client.c (debuginfod_query_server): Print the + default_progressfn terminating \n message only if that progressfn + is actually set. + +2020-03-24 Frank Ch. Eigler + + * debuginfod-find.c (main): Correct /source full-pathness check for + "debuginfod-find -v source deadbeef /pathname" case. + +2020-03-22 Frank Ch. Eigler + + * debuginfod-client.c (struct debuginfod_client): Add url field. + (struct handle_data): Add client field as backpointer. + (debuginfod_write_callback): Compute & save URL. + (default_progressfn): Print front pieces of the URL. + (debuginfod_query_server): Clear URL and cleanup after progressfn. + * debuginfod-find.c (main): Print URL at transfer conclusion. + +2020-03-22 Frank Ch. Eigler + + * debuginfod.h, libdebuginfod.map: New functions for _get/set_user(). + * debuginfod-client.c: Implement them. + * debuginfod-find.c: Include a token call just for testing them. + +2020-03-03 Aaron Merey + + * debuginfod-client.c (debuginfod_query_server): Update + cache_path even when new default path already exists. + +2020-02-27 Aaron Merey + + * debuginfod-client.c (xalloc_str): New macro. Call + asprintf with error checking. + (debuginfod_query_server): Use XDG_CACHE_HOME as a default + cache location if it is set. Replace snprintf with xalloc_str. + +2020-02-26 Konrad Kleine + + * debuginfod-client.c (debuginfod_query_server): Handle curl's + response code correctly when DEBUGINFOD_URLS begin with file:// + +2020-02-25 Frank Ch. Eigler + + * debuginfod.cxx (parse_opt): Treat -R as if -Z.rpm . + +2020-02-25 Frank Ch. Eigler + + * debuginfod.cxx (fdcache_prefetch): New parameter. + (parse_opt): Parse it. + (main): Default it. + (fdcache::fd_size_mb): Change to double for accuracy. + (fdcache::probe): New function. + (fdcache::intern): New option to intern at end of LRU. + (fdcache::lookup): Clean fdcache. + (handle_buildid_r_match): Implement multi-stage archive + parsing, with optional prefetching of extracted contents + into the fdcache. + 2020-02-19 Aaron Merey * debuginfod-client.c (debuginfod_clean_cache): Restrict diff --git a/libdrgn/elfutils/debuginfod/Makefile.am b/libdrgn/elfutils/debuginfod/Makefile.am index dcae77d07..a811e2dd1 100644 --- a/libdrgn/elfutils/debuginfod/Makefile.am +++ b/libdrgn/elfutils/debuginfod/Makefile.am @@ -64,7 +64,7 @@ debuginfod_SOURCES = debuginfod.cxx debuginfod_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(libmicrohttpd_LIBS) $(libcurl_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -lpthread -ldl debuginfod_find_SOURCES = debuginfod-find.c -debuginfod_find_LDADD = $(libeu) $(libdebuginfod) +debuginfod_find_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) noinst_LIBRARIES = libdebuginfod.a noinst_LIBRARIES += libdebuginfod_pic.a diff --git a/libdrgn/elfutils/debuginfod/debuginfod-client.c b/libdrgn/elfutils/debuginfod/debuginfod-client.c index 186aa90a5..a7dfbfb18 100644 --- a/libdrgn/elfutils/debuginfod/debuginfod-client.c +++ b/libdrgn/elfutils/debuginfod/debuginfod-client.c @@ -79,6 +79,20 @@ struct debuginfod_client /* Progress/interrupt callback function. */ debuginfod_progressfn_t progressfn; + /* Stores user data. */ + void* user_data; + + /* Stores current/last url, if any. */ + char* url; + + /* Accumulates outgoing http header names/values. */ + int user_agent_set_p; /* affects add_default_headers */ + struct curl_slist *headers; + + /* Flags the default_progressfn having printed something that + debuginfod_end needs to terminate. */ + int default_progressfn_printed_p; + /* Can contain all other context, like cache_path, server_urls, timeout or other info gotten from environment variables, the handle data, etc. So those don't have to be reparsed and @@ -99,6 +113,7 @@ static const time_t cache_default_max_unused_age_s = 604800; /* 1 week */ /* Location of the cache of files downloaded from debuginfods. The default parent directory is $HOME, or '/' if $HOME doesn't exist. */ static const char *cache_default_name = ".debuginfod_client_cache"; +static const char *cache_xdg_name = "debuginfod_client"; static const char *cache_path_envvar = DEBUGINFOD_CACHE_PATH_ENV_VAR; /* URLs of debuginfods, separated by url_delim. */ @@ -124,6 +139,9 @@ struct handle_data /* This handle. */ CURL *handle; + /* The client object whom we're serving. */ + debuginfod_client *client; + /* Pointer to handle that should write to fd. Initially points to NULL, then points to the first handle that begins writing the target file to the cache. Used to ensure that a file is not downloaded from @@ -140,7 +158,17 @@ debuginfod_write_callback (char *ptr, size_t size, size_t nmemb, void *data) /* Indicate to other handles that they can abort their transfer. */ if (*d->target_handle == NULL) - *d->target_handle = d->handle; + { + *d->target_handle = d->handle; + /* update the client object */ + const char *url = NULL; + (void) curl_easy_getinfo (d->handle, CURLINFO_EFFECTIVE_URL, &url); + if (url) + { + free (d->client->url); + d->client->url = strdup(url); /* ok if fails */ + } + } /* If this handle isn't the target handle, abort transfer. */ if (*d->target_handle != d->handle) @@ -291,8 +319,11 @@ debuginfod_clean_cache(debuginfod_client *c, static void -add_extra_headers(CURL *handle) +add_default_headers(debuginfod_client *client) { + if (client->user_agent_set_p) + return; + /* Compute a User-Agent: string to send. The more accurately this describes this host, the likelier that the debuginfod servers might be able to locate debuginfo for us. */ @@ -352,7 +383,7 @@ add_extra_headers(CURL *handle) } char *ua = NULL; - rc = asprintf(& ua, "%s/%s,%s,%s/%s", + rc = asprintf(& ua, "User-Agent: %s/%s,%s,%s/%s", PACKAGE_NAME, PACKAGE_VERSION, utspart ?: "", id ?: "", @@ -361,7 +392,7 @@ add_extra_headers(CURL *handle) ua = NULL; if (ua) - curl_easy_setopt(handle, CURLOPT_USERAGENT, (void*) ua); /* implicit strdup */ + (void) debuginfod_add_http_header (client, ua); free (ua); free (id); @@ -370,6 +401,52 @@ add_extra_headers(CURL *handle) } +#define xalloc_str(p, fmt, args...) \ + do \ + { \ + if (asprintf (&p, fmt, args) < 0) \ + { \ + p = NULL; \ + rc = -ENOMEM; \ + goto out; \ + } \ + } while (0) + + +/* Offer a basic form of progress tracing */ +static int +default_progressfn (debuginfod_client *c, long a, long b) +{ + const char* url = debuginfod_get_url (c); + int len = 0; + + /* We prefer to print the host part of the URL to keep the + message short. */ + if (url != NULL) + { + const char* buildid = strstr(url, "buildid/"); + if (buildid != NULL) + len = (buildid - url); + else + len = strlen(url); + } + + if (b == 0 || url==NULL) /* early stage */ + dprintf(STDERR_FILENO, + "\rDownloading %c", "-/|\\"[a % 4]); + else if (b < 0) /* download in progress but unknown total length */ + dprintf(STDERR_FILENO, + "\rDownloading from %.*s %ld", + len, url, a); + else /* download in progress, and known total length */ + dprintf(STDERR_FILENO, + "\rDownloading from %.*s %ld/%ld", + len, url, a, b); + c->default_progressfn_printed_p = 1; + + return 0; +} + /* Query each of the server URLs found in $DEBUGINFOD_URLS for the file with the specified build-id, type (debuginfo, executable or source) @@ -384,18 +461,24 @@ debuginfod_query_server (debuginfod_client *c, const char *filename, char **path) { - char *urls_envvar; char *server_urls; - char cache_path[PATH_MAX]; - char maxage_path[PATH_MAX*3]; /* These *3 multipliers are to shut up gcc -Wformat-truncation */ - char interval_path[PATH_MAX*4]; - char target_cache_dir[PATH_MAX*2]; - char target_cache_path[PATH_MAX*4]; - char target_cache_tmppath[PATH_MAX*5]; - char suffix[PATH_MAX*2]; + char *urls_envvar; + char *cache_path = NULL; + char *maxage_path = NULL; + char *interval_path = NULL; + char *target_cache_dir = NULL; + char *target_cache_path = NULL; + char *target_cache_tmppath = NULL; + char suffix[PATH_MAX]; char build_id_bytes[MAX_BUILD_ID_BYTES * 2 + 1]; int rc; + /* Clear the obsolete URL from a previous _find operation. */ + free (c->url); + c->url = NULL; + + add_default_headers(c); + /* Is there any server we can query? If not, don't do any work, just return with ENOSYS. Don't even access the cache. */ urls_envvar = getenv(server_urls_envvar); @@ -452,30 +535,74 @@ debuginfod_query_server (debuginfod_client *c, /* set paths needed to perform the query example format - cache_path: $HOME/.debuginfod_cache - target_cache_dir: $HOME/.debuginfod_cache/0123abcd - target_cache_path: $HOME/.debuginfod_cache/0123abcd/debuginfo - target_cache_path: $HOME/.debuginfod_cache/0123abcd/source#PATH#TO#SOURCE ? + cache_path: $HOME/.cache + target_cache_dir: $HOME/.cache/0123abcd + target_cache_path: $HOME/.cache/0123abcd/debuginfo + target_cache_path: $HOME/.cache/0123abcd/source#PATH#TO#SOURCE ? + + $XDG_CACHE_HOME takes priority over $HOME/.cache. + $DEBUGINFOD_CACHE_PATH takes priority over $HOME/.cache and $XDG_CACHE_HOME. */ - if (getenv(cache_path_envvar)) - strcpy(cache_path, getenv(cache_path_envvar)); + /* Determine location of the cache. The path specified by the debuginfod + cache environment variable takes priority. */ + char *cache_var = getenv(cache_path_envvar); + if (cache_var != NULL && strlen (cache_var) > 0) + xalloc_str (cache_path, "%s", cache_var); else { - if (getenv("HOME")) - sprintf(cache_path, "%s/%s", getenv("HOME"), cache_default_name); - else - sprintf(cache_path, "/%s", cache_default_name); + /* If a cache already exists in $HOME ('/' if $HOME isn't set), then use + that. Otherwise use the XDG cache directory naming format. */ + xalloc_str (cache_path, "%s/%s", getenv ("HOME") ?: "/", cache_default_name); + + struct stat st; + if (stat (cache_path, &st) < 0) + { + char cachedir[PATH_MAX]; + char *xdg = getenv ("XDG_CACHE_HOME"); + + if (xdg != NULL && strlen (xdg) > 0) + snprintf (cachedir, PATH_MAX, "%s", xdg); + else + snprintf (cachedir, PATH_MAX, "%s/.cache", getenv ("HOME") ?: "/"); + + /* Create XDG cache directory if it doesn't exist. */ + if (stat (cachedir, &st) == 0) + { + if (! S_ISDIR (st.st_mode)) + { + rc = -EEXIST; + goto out; + } + } + else + { + rc = mkdir (cachedir, 0700); + + /* Also check for EEXIST and S_ISDIR in case another client just + happened to create the cache. */ + if (rc < 0 + && (errno != EEXIST + || stat (cachedir, &st) != 0 + || ! S_ISDIR (st.st_mode))) + { + rc = -errno; + goto out; + } + } + + free (cache_path); + xalloc_str (cache_path, "%s/%s", cachedir, cache_xdg_name); + } } - /* avoid using snprintf here due to compiler warning. */ - snprintf(target_cache_dir, sizeof(target_cache_dir), "%s/%s", cache_path, build_id_bytes); - snprintf(target_cache_path, sizeof(target_cache_path), "%s/%s%s", target_cache_dir, type, suffix); - snprintf(target_cache_tmppath, sizeof(target_cache_tmppath), "%s.XXXXXX", target_cache_path); + xalloc_str (target_cache_dir, "%s/%s", cache_path, build_id_bytes); + xalloc_str (target_cache_path, "%s/%s%s", target_cache_dir, type, suffix); + xalloc_str (target_cache_tmppath, "%s.XXXXXX", target_cache_path); /* XXX combine these */ - snprintf(interval_path, sizeof(interval_path), "%s/%s", cache_path, cache_clean_interval_filename); - snprintf(maxage_path, sizeof(maxage_path), "%s/%s", cache_path, cache_max_unused_age_filename); + xalloc_str (interval_path, "%s/%s", cache_path, cache_clean_interval_filename); + xalloc_str (maxage_path, "%s/%s", cache_path, cache_max_unused_age_filename); rc = debuginfod_init_cache(cache_path, interval_path, maxage_path); if (rc != 0) goto out; @@ -490,7 +617,8 @@ debuginfod_query_server (debuginfod_client *c, /* Success!!!! */ if (path != NULL) *path = strdup(target_cache_path); - return fd; + rc = fd; + goto out; } long timeout = default_timeout; @@ -561,6 +689,7 @@ debuginfod_query_server (debuginfod_client *c, data[i].fd = fd; data[i].target_handle = &target_handle; data[i].handle = curl_easy_init(); + data[i].client = c; if (data[i].handle == NULL) { @@ -601,9 +730,15 @@ debuginfod_query_server (debuginfod_client *c, curl_easy_setopt(data[i].handle, CURLOPT_FOLLOWLOCATION, (long) 1); curl_easy_setopt(data[i].handle, CURLOPT_FAILONERROR, (long) 1); curl_easy_setopt(data[i].handle, CURLOPT_NOSIGNAL, (long) 1); +#if LIBCURL_VERSION_NUM >= 0x072a00 /* 7.42.0 */ + curl_easy_setopt(data[i].handle, CURLOPT_PATH_AS_IS, (long) 1); +#else + /* On old curl; no big deal, canonicalization here is almost the + same, except perhaps for ? # type decorations at the tail. */ +#endif curl_easy_setopt(data[i].handle, CURLOPT_AUTOREFERER, (long) 1); curl_easy_setopt(data[i].handle, CURLOPT_ACCEPT_ENCODING, ""); - add_extra_headers(data[i].handle); + curl_easy_setopt(data[i].handle, CURLOPT_HTTPHEADER, c->headers); curl_multi_add_handle(curlm, data[i].handle); server_url = strtok_r(NULL, url_delim, &strtok_saveptr); @@ -716,20 +851,34 @@ debuginfod_query_server (debuginfod_client *c, else { /* Query completed without an error. Confirm that the - response code is 200 and set verified_handle. */ - long resp_code = 500; - CURLcode curl_res; - - curl_res = curl_easy_getinfo(target_handle, - CURLINFO_RESPONSE_CODE, - &resp_code); + response code is 200 when using HTTP/HTTPS and 0 when + using file:// and set verified_handle. */ - if (curl_res == CURLE_OK - && resp_code == 200 - && msg->easy_handle != NULL) + if (msg->easy_handle != NULL) { - verified_handle = msg->easy_handle; - break; + char *effective_url = NULL; + long resp_code = 500; + CURLcode ok1 = curl_easy_getinfo (target_handle, + CURLINFO_EFFECTIVE_URL, + &effective_url); + CURLcode ok2 = curl_easy_getinfo (target_handle, + CURLINFO_RESPONSE_CODE, + &resp_code); + if(ok1 == CURLE_OK && ok2 == CURLE_OK && effective_url) + { + if (strncmp (effective_url, "http", 4) == 0) + if (resp_code == 200) + { + verified_handle = msg->easy_handle; + break; + } + if (strncmp (effective_url, "file", 4) == 0) + if (resp_code == 0) + { + verified_handle = msg->easy_handle; + break; + } + } } } } @@ -765,12 +914,14 @@ debuginfod_query_server (debuginfod_client *c, curl_multi_cleanup (curlm); free (data); free (server_urls); + /* don't close fd - we're returning it */ /* don't unlink the tmppath; it's already been renamed. */ if (path != NULL) *path = strdup(target_cache_path); - return fd; + rc = fd; + goto out; /* error exits */ out1: @@ -786,25 +937,25 @@ debuginfod_query_server (debuginfod_client *c, out0: free (server_urls); +/* general purpose exit */ out: + /* Conclude the last \r status line */ + /* Another possibility is to use the ANSI CSI n K EL "Erase in Line" + code. That way, the previously printed messages would be erased, + and without a newline. */ + if (c->default_progressfn_printed_p) + dprintf(STDERR_FILENO, "\n"); + + free (cache_path); + free (maxage_path); + free (interval_path); + free (target_cache_dir); + free (target_cache_path); + free (target_cache_tmppath); return rc; } -/* Activate a basic form of progress tracing */ -static int -default_progressfn (debuginfod_client *c, long a, long b) -{ - (void) c; - - dprintf(STDERR_FILENO, - "Downloading from debuginfod %ld/%ld%s", a, b, - ((a == b) ? "\n" : "\r")); - /* XXX: include URL - stateful */ - - return 0; -} - /* See debuginfod.h */ debuginfod_client * @@ -812,20 +963,42 @@ debuginfod_begin (void) { debuginfod_client *client; size_t size = sizeof (struct debuginfod_client); - client = (debuginfod_client *) malloc (size); + client = (debuginfod_client *) calloc (1, size); if (client != NULL) { if (getenv(DEBUGINFOD_PROGRESS_ENV_VAR)) client->progressfn = default_progressfn; - else - client->progressfn = NULL; } return client; } +void +debuginfod_set_user_data(debuginfod_client *client, + void *data) +{ + client->user_data = data; +} + +void * +debuginfod_get_user_data(debuginfod_client *client) +{ + return client->user_data; +} + +const char * +debuginfod_get_url(debuginfod_client *client) +{ + return client->url; +} + void debuginfod_end (debuginfod_client *client) { + if (client == NULL) + return; + + curl_slist_free_all (client->headers); + free (client->url); free (client); } @@ -859,6 +1032,33 @@ int debuginfod_find_source(debuginfod_client *client, } +/* Add an outgoing HTTP header. */ +int debuginfod_add_http_header (debuginfod_client *client, const char* header) +{ + /* Sanity check header value is of the form Header: Value. + It should contain exactly one colon that isn't the first or + last character. */ + char *colon = strchr (header, ':'); + if (colon == NULL + || colon == header + || *(colon + 1) == '\0' + || strchr (colon + 1, ':') != NULL) + return -EINVAL; + + struct curl_slist *temp = curl_slist_append (client->headers, header); + if (temp == NULL) + return -ENOMEM; + + /* Track if User-Agent: is being set. If so, signal not to add the + default one. */ + if (strncmp (header, "User-Agent:", 11) == 0) + client->user_agent_set_p = 1; + + client->headers = temp; + return 0; +} + + void debuginfod_set_progressfn(debuginfod_client *client, debuginfod_progressfn_t fn) diff --git a/libdrgn/elfutils/debuginfod/debuginfod-find.c b/libdrgn/elfutils/debuginfod/debuginfod-find.c index 8bd3a3dba..83a43ce4b 100644 --- a/libdrgn/elfutils/debuginfod/debuginfod-find.c +++ b/libdrgn/elfutils/debuginfod/debuginfod-find.c @@ -1,6 +1,6 @@ /* Command-line frontend for retrieving ELF / DWARF / source files from the debuginfod. - Copyright (C) 2019 Red Hat, Inc. + Copyright (C) 2019-2020 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -25,6 +25,10 @@ #include #include #include +#include +#include +#include +#include /* Name and version of program. */ @@ -39,8 +43,12 @@ static const char doc[] = N_("Request debuginfo-related content " /* Strings for arguments in help texts. */ static const char args_doc[] = N_("debuginfo BUILDID\n" + "debuginfo PATH\n" "executable BUILDID\n" - "source BUILDID /FILENAME"); + "executable PATH\n" + "source BUILDID /FILENAME\n" + "source PATH /FILENAME\n"); + /* Definitions of arguments for argp functions. */ static const struct argp_option options[] = @@ -51,6 +59,7 @@ static const struct argp_option options[] = /* debuginfod connection handle. */ static debuginfod_client *client; +static int verbose; int progressfn(debuginfod_client *c __attribute__((__unused__)), long a, long b) @@ -66,7 +75,8 @@ static error_t parse_opt (int key, char *arg, struct argp_state *state) (void) state; switch (key) { - case 'v': debuginfod_set_progressfn (client, & progressfn); break; + case 'v': verbose++; + debuginfod_set_progressfn (client, & progressfn); break; default: return ARGP_ERR_UNKNOWN; } return 0; @@ -84,6 +94,8 @@ static struct argp argp = int main(int argc, char** argv) { + elf_version (EV_CURRENT); + client = debuginfod_begin (); if (client == NULL) { @@ -91,6 +103,9 @@ main(int argc, char** argv) return 1; } + /* Exercise user data pointer, to support testing only. */ + debuginfod_set_user_data (client, (void *)"Progress"); + int remaining; (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL); @@ -100,29 +115,72 @@ main(int argc, char** argv) return 1; } - int rc; + /* If we were passed an ELF file name in the BUILDID slot, look in there. */ + unsigned char* build_id = (unsigned char*) argv[remaining+1]; + int build_id_len = 0; /* assume text */ + + int any_non_hex = 0; + int i; + for (i = 0; build_id[i] != '\0'; i++) + if ((build_id[i] >= '0' && build_id[i] <= '9') || + (build_id[i] >= 'a' && build_id[i] <= 'f')) + ; + else + any_non_hex = 1; + + int fd = -1; + Elf* elf = NULL; + if (any_non_hex) /* raw build-id */ + { + fd = open ((char*) build_id, O_RDONLY); + if (fd < 0) + fprintf (stderr, "Cannot open %s: %s\n", build_id, strerror(errno)); + } + if (fd >= 0) + { + elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL); + if (elf == NULL) + fprintf (stderr, "Cannot elf_begin %s: %s\n", build_id, elf_errmsg(-1)); + } + if (elf != NULL) + { + const void *extracted_build_id; + ssize_t s = dwelf_elf_gnu_build_id(elf, &extracted_build_id); + if (s > 0) + { + /* Success: replace the build_id pointer/len with the binary blob + that elfutils is keeping for us. It'll remain valid until elf_end(). */ + build_id = (unsigned char*) extracted_build_id; + build_id_len = s; + } + else + fprintf (stderr, "Cannot extract build-id from %s: %s\n", build_id, elf_errmsg(-1)); + } + char *cache_name; + int rc = 0; /* Check whether FILETYPE is valid and call the appropriate debuginfod_find_* function. If FILETYPE is "source" then ensure a FILENAME was also supplied as an argument. */ if (strcmp(argv[remaining], "debuginfo") == 0) rc = debuginfod_find_debuginfo(client, - (unsigned char *)argv[remaining+1], 0, + build_id, build_id_len, &cache_name); else if (strcmp(argv[remaining], "executable") == 0) rc = debuginfod_find_executable(client, - (unsigned char *)argv[remaining+1], 0, + build_id, build_id_len, &cache_name); else if (strcmp(argv[remaining], "source") == 0) { - if (remaining+2 == argc || argv[3][0] != '/') + if (remaining+2 == argc || argv[remaining+2][0] != '/') { fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n"); return 1; } - rc = debuginfod_find_source(client, (unsigned char *)argv[remaining+1], - 0, argv[remaining+2], &cache_name); + rc = debuginfod_find_source(client, + build_id, build_id_len, + argv[remaining+2], &cache_name); } else { @@ -130,6 +188,19 @@ main(int argc, char** argv) return 1; } + if (verbose) + { + const char* url = debuginfod_get_url (client); + if (url != NULL) + fprintf(stderr, "Downloaded from %s\n", url); + } + + debuginfod_end (client); + if (elf) + elf_end(elf); + if (fd >= 0) + close (fd); + if (rc < 0) { fprintf(stderr, "Server query failed: %s\n", strerror(-rc)); @@ -137,9 +208,7 @@ main(int argc, char** argv) } printf("%s\n", cache_name); - free (cache_name); - debuginfod_end (client); return 0; } diff --git a/libdrgn/elfutils/debuginfod/debuginfod.cxx b/libdrgn/elfutils/debuginfod/debuginfod.cxx index 0acd70e4a..76f1fa52c 100644 --- a/libdrgn/elfutils/debuginfod/debuginfod.cxx +++ b/libdrgn/elfutils/debuginfod/debuginfod.cxx @@ -355,6 +355,8 @@ static const struct argp_option options[] = { "fdcache-fds", ARGP_KEY_FDCACHE_FDS, "NUM", 0, "Maximum number of archive files to keep in fdcache.", 0 }, #define ARGP_KEY_FDCACHE_MBS 0x1002 { "fdcache-mbs", ARGP_KEY_FDCACHE_MBS, "MB", 0, "Maximum total size of archive file fdcache.", 0 }, +#define ARGP_KEY_FDCACHE_PREFETCH 0x1003 + { "fdcache-prefetch", ARGP_KEY_FDCACHE_PREFETCH, "NUM", 0, "Number of archive files to prefetch into fdcache.", 0 }, { NULL, 0, NULL, 0, NULL, 0 } }; @@ -394,6 +396,7 @@ static regex_t file_exclude_regex; static bool traverse_logical; static long fdcache_fds; static long fdcache_mbs; +static long fdcache_prefetch; static string tmpdir; static void set_metric(const string& key, int64_t value); @@ -419,15 +422,25 @@ parse_opt (int key, char *arg, case 'v': verbose ++; break; case 'd': db_path = string(arg); break; case 'p': http_port = (unsigned) atoi(arg); - if (http_port > 65535) argp_failure(state, 1, EINVAL, "port number"); + if (http_port == 0 || http_port > 65535) + argp_failure(state, 1, EINVAL, "port number"); break; case 'F': scan_files = true; break; case 'R': - scan_archives[".rpm"]="rpm2cpio"; + scan_archives[".rpm"]="cat"; // libarchive groks rpm natively break; case 'U': - scan_archives[".deb"]="dpkg-deb --fsys-tarfile"; - scan_archives[".ddeb"]="dpkg-deb --fsys-tarfile"; + if (access("/usr/bin/dpkg-deb", X_OK) == 0) + { + scan_archives[".deb"]="dpkg-deb --fsys-tarfile"; + scan_archives[".ddeb"]="dpkg-deb --fsys-tarfile"; + } + else + { + scan_archives[".deb"]="(bsdtar -O -x -f - data.tar.xz)<"; + scan_archives[".ddeb"]="(bsdtar -O -x -f - data.tar.xz)<"; + } + // .udeb too? break; case 'Z': { @@ -476,6 +489,9 @@ parse_opt (int key, char *arg, case ARGP_KEY_FDCACHE_MBS: fdcache_mbs = atol (arg); break; + case ARGP_KEY_FDCACHE_PREFETCH: + fdcache_prefetch = atol (arg); + break; case ARGP_KEY_ARG: source_paths.insert(string(arg)); break; @@ -847,6 +863,7 @@ conninfo (struct MHD_Connection * conn) //////////////////////////////////////////////////////////////////////// + static void add_mhd_last_modified (struct MHD_Response *resp, time_t mtime) { @@ -938,6 +955,82 @@ shell_escape(const string& str) } +// PR25548: Perform POSIX / RFC3986 style path canonicalization on the input string. +// +// Namely: +// // -> / +// /foo/../ -> / +// /./ -> / +// +// This mapping is done on dwarf-side source path names, which may +// include these constructs, so we can deal with debuginfod clients +// that accidentally canonicalize the paths. +// +// realpath(3) is close but not quite right, because it also resolves +// symbolic links. Symlinks at the debuginfod server have nothing to +// do with the build-time symlinks, thus they must not be considered. +// +// see also curl Curl_dedotdotify() aka RFC3986, which we mostly follow here +// see also libc __realpath() +// see also llvm llvm::sys::path::remove_dots() +static string +canon_pathname (const string& input) +{ + string i = input; // 5.2.4 (1) + string o; + + while (i.size() != 0) + { + // 5.2.4 (2) A + if (i.substr(0,3) == "../") + i = i.substr(3); + else if(i.substr(0,2) == "./") + i = i.substr(2); + + // 5.2.4 (2) B + else if (i.substr(0,3) == "/./") + i = i.substr(2); + else if (i == "/.") + i = ""; // no need to handle "/." complete-path-segment case; we're dealing with file names + + // 5.2.4 (2) C + else if (i.substr(0,4) == "/../") { + i = i.substr(3); + string::size_type sl = o.rfind("/"); + if (sl != string::npos) + o = o.substr(0, sl); + else + o = ""; + } else if (i == "/..") + i = ""; // no need to handle "/.." complete-path-segment case; we're dealing with file names + + // 5.2.4 (2) D + // no need to handle these cases; we're dealing with file names + else if (i == ".") + i = ""; + else if (i == "..") + i = ""; + + // POSIX special: map // to / + else if (i.substr(0,2) == "//") + i = i.substr(1); + + // 5.2.4 (2) E + else { + string::size_type next_slash = i.find("/", (i[0]=='/' ? 1 : 0)); // skip first slash + o += i.substr(0, next_slash); + if (next_slash == string::npos) + i = ""; + else + i = i.substr(next_slash); + } + } + + return o; +} + + + // A map-like class that owns a cache of file descriptors (indexed by // file / content names). // @@ -975,14 +1068,14 @@ class libarchive_fdcache string archive; string entry; string fd; - long fd_size_mb; // rounded up megabytes + double fd_size_mb; // slightly rounded up megabytes }; deque lru; // @head: most recently used long max_fds; long max_mbs; public: - void intern(const string& a, const string& b, string fd, off_t sz) + void intern(const string& a, const string& b, string fd, off_t sz, bool front_p) { { unique_lock lock(fdcache_lock); @@ -995,31 +1088,56 @@ class libarchive_fdcache break; // must not continue iterating } } - long mb = ((sz+1023)/1024+1023)/1024; + double mb = (sz+65535)/1048576.0; // round up to 64K block fdcache_entry n = { a, b, fd, mb }; - lru.push_front(n); + if (front_p) + lru.push_front(n); + else + lru.push_back(n); if (verbose > 3) - obatched(clog) << "fdcache interned a=" << a << " b=" << b << " fd=" << fd << " mb=" << mb << endl; + obatched(clog) << "fdcache interned a=" << a << " b=" << b + << " fd=" << fd << " mb=" << mb << " front=" << front_p << endl; } - this->limit(max_fds, max_mbs); // age cache if required + // NB: we age the cache at lookup time too + if (front_p) + this->limit(max_fds, max_mbs); // age cache if required } int lookup(const string& a, const string& b) + { + int fd = -1; + { + unique_lock lock(fdcache_lock); + for (auto i = lru.begin(); i < lru.end(); i++) + { + if (i->archive == a && i->entry == b) + { // found it; move it to head of lru + fdcache_entry n = *i; + lru.erase(i); // invalidates i, so no more iteration! + lru.push_front(n); + + fd = open(n.fd.c_str(), O_RDONLY); // NB: no problem if dup() fails; looks like cache miss + break; + } + } + } + + if (fd >= 0) + this->limit(max_fds, max_mbs); // age cache if required + + return fd; + } + + int probe(const string& a, const string& b) // just a cache residency check - don't modify LRU state, don't open { unique_lock lock(fdcache_lock); for (auto i = lru.begin(); i < lru.end(); i++) { if (i->archive == a && i->entry == b) - { // found it; move it to head of lru - fdcache_entry n = *i; - lru.erase(i); // invalidates i, so no more iteration! - lru.push_front(n); - - return open(n.fd.c_str(), O_RDONLY); // NB: no problem if dup() fails; looks like cache miss - } + return true; } - return -1; + return false; } void clear(const string& a, const string& b) @@ -1047,7 +1165,7 @@ class libarchive_fdcache this->max_mbs = maxmbs; long total_fd = 0; - long total_mb = 0; + double total_mb = 0.0; for (auto i = lru.begin(); i < lru.end(); i++) { // accumulate totals from most recently used one going backward @@ -1117,6 +1235,7 @@ handle_buildid_r_match (int64_t b_mtime, return 0; } + // check for a match in the fdcache first int fd = fdcache.lookup(b_source0, b_source1); while (fd >= 0) // got one!; NB: this is really an if() with a possible branch out to the end { @@ -1152,6 +1271,7 @@ handle_buildid_r_match (int64_t b_mtime, // NB: see, we never go around the 'loop' more than once } + // no match ... grumble, must process the archive string archive_decoder = "/dev/null"; string archive_extension = ""; for (auto&& arch : scan_archives) @@ -1196,8 +1316,19 @@ handle_buildid_r_match (int64_t b_mtime, if (rc != ARCHIVE_OK) throw archive_exception(a, "cannot open archive from pipe"); - while(1) // parse cpio archive entries + // archive traversal is in three stages, no, four stages: + // 1) skip entries whose names do not match the requested one + // 2) extract the matching entry name (set r = result) + // 3) extract some number of prefetched entries (just into fdcache) + // 4) abort any further processing + struct MHD_Response* r = 0; // will set in stage 2 + unsigned prefetch_count = fdcache_prefetch; // will decrement in stage 3 + + while(r == 0 || prefetch_count > 0) // stage 1, 2, or 3 { + if (interrupted) + break; + struct archive_entry *e; rc = archive_read_next_header (a, &e); if (rc != ARCHIVE_OK) @@ -1207,7 +1338,10 @@ handle_buildid_r_match (int64_t b_mtime, continue; string fn = canonicalized_archive_entry_pathname (e); - if (fn != b_source1) + if ((r == 0) && (fn != b_source1)) // stage 1 + continue; + + if (fdcache.probe (b_source0, fn)) // skip if already interned continue; // extract this file to a temporary file @@ -1229,18 +1363,39 @@ handle_buildid_r_match (int64_t b_mtime, throw archive_exception(a, "cannot extract file"); } + // Set the mtime so the fdcache file mtimes, even prefetched ones, + // propagate to future webapi clients. + struct timeval tvs[2]; + tvs[0].tv_sec = tvs[1].tv_sec = archive_entry_mtime(e); + tvs[0].tv_usec = tvs[1].tv_usec = 0; + (void) futimes (fd, tvs); /* best effort */ + + if (r != 0) // stage 3 + { + // NB: now we know we have a complete reusable file; make fdcache + // responsible for unlinking it later. + fdcache.intern(b_source0, fn, + tmppath, archive_entry_size(e), + false); // prefetched ones go to back of lru + prefetch_count --; + close (fd); // we're not saving this fd to make a mhd-response from! + continue; + } + // NB: now we know we have a complete reusable file; make fdcache // responsible for unlinking it later. - fdcache.intern(b_source0, b_source1, tmppath, archive_entry_size(e)); + fdcache.intern(b_source0, b_source1, + tmppath, archive_entry_size(e), + true); // requested ones go to the front of lru inc_metric ("http_responses_total","result",archive_extension + " archive"); - struct MHD_Response* r = MHD_create_response_from_fd (archive_entry_size(e), fd); + r = MHD_create_response_from_fd (archive_entry_size(e), fd); if (r == 0) { if (verbose) obatched(clog) << "cannot create fd-response for " << b_source0 << endl; close(fd); - break; // assume no chance of better luck around another iteration + break; // assume no chance of better luck around another iteration; no other copies of same file } else { @@ -1251,12 +1406,12 @@ handle_buildid_r_match (int64_t b_mtime, /* libmicrohttpd will close it. */ if (result_fd) *result_fd = fd; - return r; + continue; } } // XXX: rpm/file not found: delete this R entry? - return 0; + return r; } @@ -1286,11 +1441,12 @@ debuginfod_find_progress (debuginfod_client *, long a, long b) } -static struct MHD_Response* handle_buildid (const string& buildid /* unsafe */, - const string& artifacttype /* unsafe */, - const string& suffix /* unsafe */, - int *result_fd - ) +static struct MHD_Response* +handle_buildid (MHD_Connection* conn, + const string& buildid /* unsafe */, + const string& artifacttype /* unsafe */, + const string& suffix /* unsafe */, + int *result_fd) { // validate artifacttype string atype_code; @@ -1332,12 +1488,17 @@ static struct MHD_Response* handle_buildid (const string& buildid /* unsafe */, } else if (atype_code == "S") { + // PR25548 + // Incoming source queries may come in with either dwarf-level OR canonicalized paths. + // We let the query pass with either one. + pp = new sqlite_ps (db, "mhd-query-s", - "select mtime, sourcetype, source0, source1 from " BUILDIDS "_query_s where buildid = ? and artifactsrc = ? " + "select mtime, sourcetype, source0, source1 from " BUILDIDS "_query_s where buildid = ? and artifactsrc in (?,?) " "order by sharedprefix(source0,source0ref) desc, mtime desc"); pp->reset(); pp->bind(1, buildid); pp->bind(2, suffix); + pp->bind(3, canon_pathname(suffix)); } unique_ptr ps_closer(pp); // release pp if exception or return @@ -1374,6 +1535,35 @@ static struct MHD_Response* handle_buildid (const string& buildid /* unsafe */, { debuginfod_set_progressfn (client, & debuginfod_find_progress); + if (conn) + { + // Transcribe incoming User-Agent: + string ua = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, "User-Agent") ?: ""; + string ua_complete = string("User-Agent: ") + ua; + debuginfod_add_http_header (client, ua_complete.c_str()); + + // Compute larger XFF:, for avoiding info loss during + // federation, and for future cyclicity detection. + string xff = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, "X-Forwarded-For") ?: ""; + if (xff != "") + xff += string(", "); // comma separated list + + // Compute the client's numeric IP address only - so can't merge with conninfo() + const union MHD_ConnectionInfo *u = MHD_get_connection_info (conn, + MHD_CONNECTION_INFO_CLIENT_ADDRESS); + struct sockaddr *so = u ? u->client_addr : 0; + char hostname[256] = ""; // RFC1035 + if (so && so->sa_family == AF_INET) + (void) getnameinfo (so, sizeof (struct sockaddr_in), hostname, sizeof (hostname), NULL, 0, + NI_NUMERICHOST); + else if (so && so->sa_family == AF_INET6) + (void) getnameinfo (so, sizeof (struct sockaddr_in6), hostname, sizeof (hostname), NULL, 0, + NI_NUMERICHOST); + + string xff_complete = string("X-Forwarded-For: ")+xff+string(hostname); + debuginfod_add_http_header (client, xff_complete.c_str()); + } + if (artifacttype == "debuginfo") fd = debuginfod_find_debuginfo (client, (const unsigned char*) buildid.c_str(), @@ -1412,8 +1602,16 @@ static struct MHD_Response* handle_buildid (const string& buildid /* unsafe */, } close (fd); } - else if (fd != -ENOSYS) // no DEBUGINFOD_URLS configured - throw libc_exception(-fd, "upstream debuginfod query failed"); + else + switch(fd) + { + case -ENOSYS: + break; + case -ENOENT: + break; + default: // some more tricky error + throw libc_exception(-fd, "upstream debuginfod query failed"); + } throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found"); } @@ -1503,7 +1701,7 @@ add_metric(const string& metric, static struct MHD_Response* -handle_metrics () +handle_metrics (off_t* size) { stringstream o; { @@ -1515,6 +1713,7 @@ handle_metrics () MHD_Response* r = MHD_create_response_from_buffer (os.size(), (void*) os.c_str(), MHD_RESPMEM_MUST_COPY); + *size = os.size(); MHD_add_response_header (r, "Content-Type", "text/plain"); return r; } @@ -1537,8 +1736,11 @@ handler_cb (void * /*cls*/, struct MHD_Response *r = NULL; string url_copy = url; - if (verbose) - obatched(clog) << conninfo(connection) << " " << method << " " << url << endl; + int rc = MHD_NO; // mhd + int http_code = 500; + off_t http_size = -1; + struct timeval tv_start, tv_end; + gettimeofday (&tv_start, NULL); try { @@ -1571,12 +1773,21 @@ handler_cb (void * /*cls*/, } inc_metric("http_requests_total", "type", artifacttype); - r = handle_buildid(buildid, artifacttype, suffix, 0); // NB: don't care about result-fd + // get the resulting fd so we can report its size + int fd; + r = handle_buildid(connection, buildid, artifacttype, suffix, &fd); + if (r) + { + struct stat fs; + if (fstat(fd, &fs) == 0) + http_size = fs.st_size; + // libmicrohttpd will close (fd); + } } else if (url1 == "/metrics") { inc_metric("http_requests_total", "type", "metrics"); - r = handle_metrics(); + r = handle_metrics(& http_size); } else throw reportable_exception("webapi error, unrecognized /operation"); @@ -1584,16 +1795,39 @@ handler_cb (void * /*cls*/, if (r == 0) throw reportable_exception("internal error, missing response"); - int rc = MHD_queue_response (connection, MHD_HTTP_OK, r); + rc = MHD_queue_response (connection, MHD_HTTP_OK, r); + http_code = MHD_HTTP_OK; MHD_destroy_response (r); - return rc; } catch (const reportable_exception& e) { inc_metric("http_responses_total","result","error"); e.report(clog); - return e.mhd_send_response (connection); + http_code = e.code; + http_size = e.message.size(); + rc = e.mhd_send_response (connection); } + + gettimeofday (&tv_end, NULL); + double deltas = (tv_end.tv_sec - tv_start.tv_sec) + (tv_end.tv_usec - tv_start.tv_usec)*0.000001; + obatched(clog) << conninfo(connection) + << ' ' << method << ' ' << url + << ' ' << http_code << ' ' << http_size + << ' ' << (int)(deltas*1000) << "ms" + << endl; + + // related prometheus metrics + string http_code_str = to_string(http_code); + if (http_size >= 0) + add_metric("http_responses_transfer_bytes_sum","code",http_code_str, + http_size); + inc_metric("http_responses_transfer_bytes_count","code",http_code_str); + + add_metric("http_responses_duration_milliseconds_sum","code",http_code_str, + deltas*1000); // prometheus prefers _seconds and floating point + inc_metric("http_responses_duration_milliseconds_count","code",http_code_str); + + return rc; } @@ -1640,7 +1874,7 @@ dwarf_extract_source_paths (Elf *elf, set& debug_sourcefiles) struct MHD_Response *r = 0; try { - r = handle_buildid (buildid, "debuginfo", "", &alt_fd); + r = handle_buildid (0, buildid, "debuginfo", "", &alt_fd); } catch (const reportable_exception& e) { @@ -2022,6 +2256,27 @@ scan_source_file (const string& rps, const stat_t& st, .bind(4, sfs.st_mtime) .step_ok_done(); + // PR25548: also store canonicalized source path + string dwarfsrc_canon = canon_pathname (dwarfsrc); + if (dwarfsrc_canon != dwarfsrc) + { + if (verbose > 3) + obatched(clog) << "canonicalized src=" << dwarfsrc << " alias=" << dwarfsrc_canon << endl; + + ps_upsert_files + .reset() + .bind(1, dwarfsrc_canon) + .step_ok_done(); + + ps_upsert_s + .reset() + .bind(1, buildid) + .bind(2, dwarfsrc_canon) + .bind(3, srps) + .bind(4, sfs.st_mtime) + .step_ok_done(); + } + inc_metric("found_sourcerefs_total","source","files"); } } @@ -2183,6 +2438,26 @@ archive_classify (const string& rps, string& archive_extension, .bind(2, s) .step_ok_done(); + // PR25548: also store canonicalized source path + const string& dwarfsrc = s; + string dwarfsrc_canon = canon_pathname (dwarfsrc); + if (dwarfsrc_canon != dwarfsrc) + { + if (verbose > 3) + obatched(clog) << "canonicalized src=" << dwarfsrc << " alias=" << dwarfsrc_canon << endl; + + ps_upsert_files + .reset() + .bind(1, dwarfsrc_canon) + .step_ok_done(); + + ps_upsert_sref + .reset() + .bind(1, buildid) + .bind(2, dwarfsrc_canon) + .step_ok_done(); + } + fts_sref ++; } } @@ -2809,7 +3084,8 @@ main (int argc, char *argv[]) fdcache_mbs = 1024; // 1 gigabyte else fdcache_mbs = sfs.f_bavail * sfs.f_bsize / 1024 / 1024 / 4; // 25% of free space - fdcache_fds = concurrency * 2; + fdcache_prefetch = 64; // guesstimate storage is this much less costly than re-decompression + fdcache_fds = (concurrency + fdcache_prefetch) * 2; /* Parse and process arguments. */ int remaining; @@ -2943,6 +3219,7 @@ main (int argc, char *argv[]) obatched(clog) << "rescan time " << rescan_s << endl; obatched(clog) << "fdcache fds " << fdcache_fds << endl; obatched(clog) << "fdcache mbs " << fdcache_mbs << endl; + obatched(clog) << "fdcache prefetch " << fdcache_prefetch << endl; obatched(clog) << "fdcache tmpdir " << tmpdir << endl; obatched(clog) << "groom time " << groom_s << endl; if (scan_archives.size()>0) diff --git a/libdrgn/elfutils/debuginfod/debuginfod.h b/libdrgn/elfutils/debuginfod/debuginfod.h index b4b6a3d2a..8d90838b4 100644 --- a/libdrgn/elfutils/debuginfod/debuginfod.h +++ b/libdrgn/elfutils/debuginfod/debuginfod.h @@ -1,5 +1,5 @@ /* External declarations for the libdebuginfod client library. - Copyright (C) 2019 Red Hat, Inc. + Copyright (C) 2019-2020 Red Hat, Inc. This file is part of elfutils. This file is free software; you can redistribute it and/or modify @@ -54,7 +54,7 @@ debuginfod_client *debuginfod_begin (void); return a posix error code. If successful, set *path to a strdup'd copy of the name of the same file in the cache. Caller must free() it later. */ - + int debuginfod_find_debuginfo (debuginfod_client *client, const unsigned char *build_id, int build_id_len, @@ -75,6 +75,18 @@ typedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b); void debuginfod_set_progressfn(debuginfod_client *c, debuginfod_progressfn_t fn); +/* Set the user parameter. */ +void debuginfod_set_user_data (debuginfod_client *client, void *value); + +/* Get the user parameter. */ +void* debuginfod_get_user_data (debuginfod_client *client); + +/* Get the current or last active URL, if known. */ +const char* debuginfod_get_url (debuginfod_client *client); + +/* Add an outgoing HTTP request "Header: Value". Copies string. */ +int debuginfod_add_http_header (debuginfod_client *client, const char* header); + /* Release debuginfod client connection context handle. */ void debuginfod_end (debuginfod_client *client); diff --git a/libdrgn/elfutils/debuginfod/libdebuginfod.map b/libdrgn/elfutils/debuginfod/libdebuginfod.map index 0d26f93e0..b8edfb016 100644 --- a/libdrgn/elfutils/debuginfod/libdebuginfod.map +++ b/libdrgn/elfutils/debuginfod/libdebuginfod.map @@ -8,3 +8,10 @@ ELFUTILS_0.178 { debuginfod_find_source; debuginfod_set_progressfn; } ELFUTILS_0; +ELFUTILS_0.179 { + global: + debuginfod_set_user_data; + debuginfod_get_user_data; + debuginfod_get_url; + debuginfod_add_http_header; +}; diff --git a/libdrgn/elfutils/doc/ChangeLog b/libdrgn/elfutils/doc/ChangeLog index 36094d002..f598b7f27 100644 --- a/libdrgn/elfutils/doc/ChangeLog +++ b/libdrgn/elfutils/doc/ChangeLog @@ -1,3 +1,52 @@ +2020-03-29 Mark Wielaard + + * debuginfod_find_debuginfo.3 (HTTP HEADER): Document the expected + header format and purpose. + +2020-03-28 Frank Ch. Eigler + + * debuginfod.8: Document valid --port=NUM range, excludes 0. + +2020-03-27 Frank Ch. Eigler + + * debuginfod-find.1: Document /path/-based buildid passing. + +2020-03-24 Frank Ch. Eigler + + * debuginfod_add_http_header.3: New function, documented ... + * debuginfod_find_debuginfo.3: ... here. + * Makefile.am (notrans_dist_*_man3): Add it. + +2020-03-26 Frank Ch. Eigler + + * debuginfod.8 (-R): Note zstd compression complications + and workaround. + +2020-03-24 Frank Ch. Eigler + + * debuginfod-find.1, debuginfod_find_debuginfo.3: Document + source path canonicalization. + +2020-03-22 Frank Ch. Eigler + + * debuginfod_get_url.3: New function, documented ... + * debuginfod_find_debuginfo.3: ... here. + * Makefile.am (notrans_dist_*_man3): Add it. + +2020-03-22 Frank Ch. Eigler + + * debuginfod_get_user.3, _set_user.3: New functions, documented ... + * debuginfod_find_debuginfo.3: ... here. + * Makefile.am (notrans_dist_*_man3): List all debuginfod .3 functions. + +2020-02-25 Frank Ch. Eigler + + * debuginfod.8: Note that -R works just like -Z.rpm . + +2020-02-25 Frank Ch. Eigler + + * debuginfod.8: Document new --fdcache-prefetch option. + 2020-02-05 Frank Ch. Eigler * debuginfod.8: Document new -Z flag and tweak other bits. diff --git a/libdrgn/elfutils/doc/Makefile.am b/libdrgn/elfutils/doc/Makefile.am index b5db01ff7..f0c7e55df 100644 --- a/libdrgn/elfutils/doc/Makefile.am +++ b/libdrgn/elfutils/doc/Makefile.am @@ -1,7 +1,7 @@ ## Process this file with automake to create Makefile.in ## Configure input file for elfutils. ## -## Copyright (C) 1996-2001, 2002, 2005, 2019 Red Hat, Inc. +## Copyright (C) 1996-2001, 2002, 2005, 2019-2020 Red Hat, Inc. ## This file is part of elfutils. ## ## This file is free software; you can redistribute it and/or modify @@ -24,7 +24,16 @@ notrans_dist_man1_MANS= if DEBUGINFOD notrans_dist_man8_MANS += debuginfod.8 -notrans_dist_man3_MANS += debuginfod_find_debuginfo.3 debuginfod_find_source.3 debuginfod_find_executable.3 debuginfod_set_progressfn.3 +notrans_dist_man3_MANS += debuginfod_add_http_header.3 +notrans_dist_man3_MANS += debuginfod_begin.3 +notrans_dist_man3_MANS += debuginfod_end.3 +notrans_dist_man3_MANS += debuginfod_find_debuginfo.3 +notrans_dist_man3_MANS += debuginfod_find_executable.3 +notrans_dist_man3_MANS += debuginfod_find_source.3 +notrans_dist_man3_MANS += debuginfod_get_user_data.3 +notrans_dist_man3_MANS += debuginfod_get_url.3 +notrans_dist_man3_MANS += debuginfod_set_progressfn.3 +notrans_dist_man3_MANS += debuginfod_set_user_data.3 notrans_dist_man1_MANS += debuginfod-find.1 endif diff --git a/libdrgn/elfutils/doc/debuginfod-find.1 b/libdrgn/elfutils/doc/debuginfod-find.1 index e71ca29be..aeb1cb120 100644 --- a/libdrgn/elfutils/doc/debuginfod-find.1 +++ b/libdrgn/elfutils/doc/debuginfod-find.1 @@ -19,10 +19,11 @@ debuginfod-find \- request debuginfo-related data .SH SYNOPSIS .B debuginfod-find [\fIOPTION\fP]... debuginfo \fIBUILDID\fP - +.B debuginfod-find [\fIOPTION\fP]... debuginfo \fIPATH\fP .B debuginfod-find [\fIOPTION\fP]... executable \fIBUILDID\fP - +.B debuginfod-find [\fIOPTION\fP]... executable \fIPATH\fP .B debuginfod-find [\fIOPTION\fP]... source \fIBUILDID\fP \fI/FILENAME\fP +.B debuginfod-find [\fIOPTION\fP]... source \fIPATH\fP \fI/FILENAME\fP .SH DESCRIPTION \fBdebuginfod-find\fP queries one or more \fBdebuginfod\fP servers for @@ -52,6 +53,14 @@ Then the hexadecimal BUILDID is simply: 8713b9c3fb8a720137a4a08b325905c7aaf8429d .ESAMPLE +In place of the hexadecimal \fIBUILDID\fP, debuginfod-find also +accepts a path name to to an ELF binary, from which it extracts the +buildid. In this case, ensure the file name has some character other +than \fB[0-9a-f]\fP. Files ambiguously named files like +"\fBdeadbeef\fP" can be passed with a \fB./deadbeef\fP extra path +component. + + .SS debuginfo \fIBUILDID\fP If the given buildid is known to a server, this request will result @@ -78,10 +87,11 @@ is made up of multiple CUs. Therefore, to disambiguate, debuginfod expects source queries to prefix relative path names with the CU compilation-directory, followed by a mandatory "/". -Note: the user should not elide \fB../\fP or \fB/./\fP or extraneous -\fB///\fP sorts of path components in the directory names, because if -this is how those names appear in the DWARF files, that is what -debuginfod needs to see too. +Note: the caller may or may not elide \fB../\fP or \fB/./\fP or extraneous +\fB///\fP sorts of path components in the directory names. debuginfod +accepts both forms. Specifically, debuginfod canonicalizes path names +according to RFC3986 section 5.2.4 (Remove Dot Segments), plus reducing +any \fB//\fP to \fB/\fP in the path. For example: .TS diff --git a/libdrgn/elfutils/doc/debuginfod.8 b/libdrgn/elfutils/doc/debuginfod.8 index ca844aedc..a645ceed5 100644 --- a/libdrgn/elfutils/doc/debuginfod.8 +++ b/libdrgn/elfutils/doc/debuginfod.8 @@ -99,7 +99,11 @@ additional patterns. This option may be repeated. .TP .B "\-R" Activate RPM patterns in archive scanning. The default is off. -Equivalent to \fB\%\-Z\~.rpm=rpm2cpio\fP. +Equivalent to \fB\%\-Z\~.rpm=cat\fP, since libarchive can natively +process RPM archives. If your version of libarchive is much older +than 2020, be aware that some distributions have switched to an +incompatible zstd compression for their payload. You may experiment +with \fB\%\-Z\ .rpm='(rpm2cpio|zstdcat)<'\fP instead of \fB\-R\fP. .TP .B "\-U" @@ -126,9 +130,10 @@ repeated. The default is nothing extra. .TP .B "\-p NUM" "\-\-port=NUM" -Set the TCP port number on which debuginfod should listen, to service -HTTP requests. Both IPv4 and IPV6 sockets are opened, if possible. -The webapi is documented below. The default port number is 8002. +Set the TCP port number (0 < NUM < 65536) on which debuginfod should +listen, to service HTTP requests. Both IPv4 and IPV6 sockets are +opened, if possible. The webapi is documented below. The default +port number is 8002. .TP .B "\-I REGEX" "\-\-include=REGEX" "\-X REGEX" "\-\-exclude=REGEX" @@ -193,14 +198,17 @@ loops in the symbolic directory tree might lead to \fIinfinite traversal\fP. .TP -.B "\-\-fdcache-fds=NUM" "\-\-fdcache-mbs=MB" +.B "\-\-fdcache\-fds=NUM" "\-\-fdcache\-mbs=MB" "\-\-fdcache\-prefetch=NUM2" Configure limits on a cache that keeps recently extracted files from -archives. Up to NUM files and up to a total of MB megabytes will be -kept extracted, in order to avoid having to decompress their archives -again. The default NUM and MB values depend on the concurrency of the -system, and on the available disk space on the $TMPDIR or \fB/tmp\fP -filesystem. This is because that is where the most recently used -extracted files are kept. Grooming cleans this cache. +archives. Up to NUM requested files and up to a total of MB megabytes +will be kept extracted, in order to avoid having to decompress their +archives over and over again. In addition, up to NUM2 other files +from an archive may be prefetched into the cache before they are even +requested. The default NUM, NUM2, and MB values depend on the +concurrency of the system, and on the available disk space on the +$TMPDIR or \fB/tmp\fP filesystem. This is because that is where the +most recently used extracted files are kept. Grooming cleans this +cache. .TP .B "\-v" @@ -261,10 +269,11 @@ is made up of multiple CUs. Therefore, to disambiguate, debuginfod expects source queries to prefix relative path names with the CU compilation-directory, followed by a mandatory "/". -Note: contrary to RFC 3986, the client should not elide \fB../\fP or -\fB/./\fP or extraneous \fB///\fP sorts of path components in the -directory names, because if this is how those names appear in the -DWARF files, that is what debuginfod needs to see too. +Note: the caller may or may not elide \fB../\fP or \fB/./\fP or extraneous +\fB///\fP sorts of path components in the directory names. debuginfod +accepts both forms. Specifically, debuginfod canonicalizes path names +according to RFC3986 section 5.2.4 (Remove Dot Segments), plus reducing +any \fB//\fP to \fB/\fP in the path. For example: .TS @@ -406,8 +415,10 @@ or negative means "no timeout".) .B DEBUGINFOD_CACHE_PATH This environment variable governs the location of the cache where downloaded files are kept. It is cleaned periodically as this -program is reexecuted. The default is \%$HOME/.debuginfod_client_cache. -.\" XXX describe cache eviction policy +program is reexecuted. If XDG_CACHE_HOME is set then +$XDG_CACHE_HOME/debuginfod_client is the default location, otherwise +$HOME/.cache/debuginfod_client is used. For more information regarding +the client cache see \fIdebuginfod_find_debuginfo(3)\fP. .SH FILES .LP @@ -418,8 +429,10 @@ Default database file. .PD .TP 20 -.B $HOME/.debuginfod_client_cache +.B $XDG_CACHE_HOME/debuginfod_client Default cache directory for content from upstream debuginfods. +If XDG_CACHE_HOME is not set then \fB$HOME/.cache/debuginfod_client\fP +is used. .PD diff --git a/libdrgn/elfutils/doc/debuginfod_add_http_header.3 b/libdrgn/elfutils/doc/debuginfod_add_http_header.3 new file mode 100644 index 000000000..16279936e --- /dev/null +++ b/libdrgn/elfutils/doc/debuginfod_add_http_header.3 @@ -0,0 +1 @@ +.so man3/debuginfod_find_debuginfo.3 diff --git a/libdrgn/elfutils/doc/debuginfod_find_debuginfo.3 b/libdrgn/elfutils/doc/debuginfod_find_debuginfo.3 index c232ac717..d9717d734 100644 --- a/libdrgn/elfutils/doc/debuginfod_find_debuginfo.3 +++ b/libdrgn/elfutils/doc/debuginfod_find_debuginfo.3 @@ -21,9 +21,15 @@ debuginfod_find_debuginfo \- request debuginfo from debuginfod .nf .B #include .PP +Link with \fB-ldebuginfod\fP. + +CONNECTION HANDLE + .BI "debuginfod_client *debuginfod_begin(void);" .BI "void debuginfod_end(debuginfod_client *" client ");" +LOOKUP FUNCTIONS + .BI "int debuginfod_find_debuginfo(debuginfod_client *" client "," .BI " const unsigned char *" build_id "," .BI " int " build_id_len "," @@ -38,12 +44,18 @@ debuginfod_find_debuginfo \- request debuginfo from debuginfod .BI " const char *" filename "," .BI " char ** " path ");" +OPTIONAL FUNCTIONS + .BI "typedef int (*debuginfod_progressfn_t)(debuginfod_client *" client "," .BI " long a, long b);" .BI "void debuginfod_set_progressfn(debuginfod_client *" client "," .BI " debuginfod_progressfn_t " progressfn ");" - -Link with \fB-ldebuginfod\fP. +.BI "void debuginfod_set_user_data(debuginfod_client *" client "," +.BI " void *" data ");" +.BI "void* debuginfod_get_user_data(debuginfod_client *" client ");" +.BI "const char* debuginfod_get_url(debuginfod_client *" client ");" +.BI "int debuginfod_add_http_header(debuginfod_client *" client "," +.BI " const char* " header ");" .SH DESCRIPTION @@ -77,10 +89,11 @@ paths, and yet an executable is made up of multiple CUs. Therefore, to disambiguate, debuginfod expects source queries to prefix relative path names with the CU compilation-directory, followed by a mandatory "/". -Note: the caller should not elide \fB../\fP or \fB/./\fP or extraneous -\fB///\fP sorts of path components in the directory names, because if -this is how those names appear in the DWARF files, that is what -debuginfod needs to see too. +Note: the caller may or may not elide \fB../\fP or \fB/./\fP or extraneous +\fB///\fP sorts of path components in the directory names. debuginfod +accepts both forms. Specifically, debuginfod canonicalizes path names +according to RFC3986 section 5.2.4 (Remove Dot Segments), plus reducing +any \fB//\fP to \fB/\fP in the path. If \fIpath\fP is not NULL and the query is successful, \fIpath\fP is set to the path of the file in the cache. The caller must \fBfree\fP() this value. @@ -102,7 +115,12 @@ to the client cache and a file descriptor to that file is returned. The caller needs to \fBclose\fP() this descriptor. Otherwise, a negative error code is returned. -.SH "PROGRESS CALLBACK" +.SH "OPTIONAL FUNCTIONS" + +A small number of optional functions are available to tune or query +the operation of the debuginfod client. + +.SS "PROGRESS CALLBACK" As the \fBdebuginfod_find_*\fP() functions may block for seconds or longer, a progress callback function is called periodically, if @@ -125,6 +143,47 @@ continue the work, or any other value to stop work as soon as possible. Consequently, the \fBdebuginfod_find_*\fP() function will likely return with an error, but might still succeed. +.SS "USER DATA POINTER" + +A single \fIvoid *\fP pointer associated with the connection handle +may be set any time via +.BR \%debuginfod_set_user_data () , +and retrieved via +.BR \%debuginfod_get_user_data () . +The value is undefined if unset. + +.SS "URL" + +The URL of the current or most recent outgoing download, if known, +may be retrieved via +.BR \%debuginfod_get_url () +from the progressfn callback, or afterwards. It may be NULL. +The resulting string is owned by the library, and must not be modified +or freed. The caller should copy it if it is needed beyond the release +of the client object. + +.SS "HTTP HEADER" + +Before a lookup function is initiated, a client application may +add HTTP request headers to future downloads. +.BR \%debuginfod_add_http_header () +may be called with strings of the form +.BR \%"Header:\~value" . +These strings are copied by the library. A zero return value +indicates success, but out-of-memory conditions may result in +a non-zero \fI-ENOMEM\fP. If the string is in the wrong form +\fI-EINVAL\fP will be returned. + +Note that the current debuginfod-client library implementation uses +libcurl, but you shouldn't rely on that fact. Don't use this function +for replacing any standard headers, except for the User-Agent mentioned +below. The only supported usage of this function is for adding an +optional header which might or might not be passed through to the +server for logging purposes only. + +By default, the library adds a descriptive \fIUser-Agent:\fP +header to outgoing requests. If the client application adds +a header with the same name, this default is suppressed. .SH "CACHE" If the query is successful, the \fBdebuginfod_find_*\fP() functions save @@ -180,7 +239,10 @@ function output. .B DEBUGINFOD_CACHE_PATH This environment variable governs the location of the cache where downloaded files are kept. It is cleaned periodically as this -program is reexecuted. The default is $HOME/.debuginfod_client_cache. +program is reexecuted. If XDG_CACHE_HOME is set then +$XDG_CACHE_HOME/debuginfod_client is the default location, otherwise +$HOME/.cache/debuginfod_client is used. + .SH "ERRORS" The following list is not comprehensive. Error codes may also @@ -244,7 +306,8 @@ the timeout duration. See debuginfod(8) for more information. .PD .1v .TP 20 .B $HOME/.debuginfod_client_cache -Default cache directory. +Default cache directory. If XDG_CACHE_HOME is not set then +\fB$HOME/.cache/debuginfod_client\fP is used. .PD .SH "SEE ALSO" diff --git a/libdrgn/elfutils/doc/debuginfod_get_url.3 b/libdrgn/elfutils/doc/debuginfod_get_url.3 new file mode 100644 index 000000000..16279936e --- /dev/null +++ b/libdrgn/elfutils/doc/debuginfod_get_url.3 @@ -0,0 +1 @@ +.so man3/debuginfod_find_debuginfo.3 diff --git a/libdrgn/elfutils/doc/debuginfod_get_user_data.3 b/libdrgn/elfutils/doc/debuginfod_get_user_data.3 new file mode 100644 index 000000000..16279936e --- /dev/null +++ b/libdrgn/elfutils/doc/debuginfod_get_user_data.3 @@ -0,0 +1 @@ +.so man3/debuginfod_find_debuginfo.3 diff --git a/libdrgn/elfutils/doc/debuginfod_set_user_data.3 b/libdrgn/elfutils/doc/debuginfod_set_user_data.3 new file mode 100644 index 000000000..16279936e --- /dev/null +++ b/libdrgn/elfutils/doc/debuginfod_set_user_data.3 @@ -0,0 +1 @@ +.so man3/debuginfod_find_debuginfo.3 diff --git a/libdrgn/elfutils/libasm/ChangeLog b/libdrgn/elfutils/libasm/ChangeLog index 7b0d3df34..2c092abe1 100644 --- a/libdrgn/elfutils/libasm/ChangeLog +++ b/libdrgn/elfutils/libasm/ChangeLog @@ -1,3 +1,7 @@ +2020-04-25 Mark Wielaard + + * asm_end.c (text_end): Call fflush instead of fclose. + 2020-01-08 Mark Wielaard * libasm.h: Don't include libebl.h. Define an opaque Ebl handle. diff --git a/libdrgn/elfutils/libasm/asm_end.c b/libdrgn/elfutils/libasm/asm_end.c index 99e950170..3b8582fdd 100644 --- a/libdrgn/elfutils/libasm/asm_end.c +++ b/libdrgn/elfutils/libasm/asm_end.c @@ -47,7 +47,7 @@ static int text_end (AsmCtx_t *ctx __attribute__ ((unused))) { - if (fclose (ctx->out.file) != 0) + if (fflush (ctx->out.file) != 0) { __libasm_seterrno (ASM_E_IOERROR); return -1; diff --git a/libdrgn/elfutils/libcpu/ChangeLog b/libdrgn/elfutils/libcpu/ChangeLog index 707965140..a8b2b951e 100644 --- a/libdrgn/elfutils/libcpu/ChangeLog +++ b/libdrgn/elfutils/libcpu/ChangeLog @@ -1,3 +1,8 @@ +2020-04-16 Mark Wielaard + + * i386_disasm.c (i386_disasm): Replace assert with goto invalid_op + for bad prefix. + 2019-12-11 Omar Sandoval * Makefile.am (i386_lex_CFLAGS): Add -Wno-implicit-fallthrough. diff --git a/libdrgn/elfutils/libcpu/i386_disasm.c b/libdrgn/elfutils/libcpu/i386_disasm.c index 4422ffa27..32df8cd0c 100644 --- a/libdrgn/elfutils/libcpu/i386_disasm.c +++ b/libdrgn/elfutils/libcpu/i386_disasm.c @@ -407,7 +407,8 @@ i386_disasm (Ebl *ebl __attribute__((unused)), ++curr; - assert (last_prefix_bit != 0); + if (last_prefix_bit == 0) + goto invalid_op; correct_prefix = last_prefix_bit; } @@ -445,8 +446,8 @@ i386_disasm (Ebl *ebl __attribute__((unused)), the input data. */ goto do_ret; - assert (correct_prefix == 0 - || (prefixes & correct_prefix) != 0); + if (correct_prefix != 0 && (prefixes & correct_prefix) == 0) + goto invalid_op; prefixes ^= correct_prefix; if (0) @@ -473,7 +474,8 @@ i386_disasm (Ebl *ebl __attribute__((unused)), if (data == end) { - assert (prefixes != 0); + if (prefixes == 0) + goto invalid_op; goto print_prefix; } @@ -1125,6 +1127,7 @@ i386_disasm (Ebl *ebl __attribute__((unused)), } /* Invalid (or at least unhandled) opcode. */ + invalid_op: if (prefixes != 0) goto print_prefix; /* Make sure we get past the unrecognized opcode if we haven't yet. */ diff --git a/libdrgn/elfutils/libdw/ChangeLog b/libdrgn/elfutils/libdw/ChangeLog index 59f33f9e3..c75b09587 100644 --- a/libdrgn/elfutils/libdw/ChangeLog +++ b/libdrgn/elfutils/libdw/ChangeLog @@ -1,3 +1,24 @@ +2020-05-08 Mark Wielaard + + * libdw_visit_scopes.c (walk_children): Don't recurse into imported + DW_TAG_compile_units. + +2020-05-08 Mark Wielaard + + * dwarf_decl_file.c (dwarf_decl_file): Use attr CU instead of DIE + CU to resolve file name. + * dwarf_ranges.c(dwarf_ranges): Document which CU we use when. + * libdw.h (dwarf_attr_integrate): Extend documentation. + +2020-04-25 Mark Wielaard + + * libdw_alloc.c (__libdw_alloc_tail): Call Dwarf oom_handler() + when malloc fails. + +2020-04-17 Mark Wielaard + + * dwarf_begin_elf.c (check_section): Handle .gnu.debuglto_ prefix. + 2019-10-28 Aaron Merey * Makefile.am (libdw_so_LDLIBS): Add -ldl for libdebuginfod.so dlopen. diff --git a/libdrgn/elfutils/libdw/dwarf_begin_elf.c b/libdrgn/elfutils/libdw/dwarf_begin_elf.c index 853430882..474ed1389 100644 --- a/libdrgn/elfutils/libdw/dwarf_begin_elf.c +++ b/libdrgn/elfutils/libdw/dwarf_begin_elf.c @@ -137,6 +137,10 @@ check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp) gnu_compressed = true; break; } + else if (scnlen > 14 /* .gnu.debuglto_ prefix. */ + && strncmp (scnname, ".gnu.debuglto_", 14) == 0 + && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0) + break; } if (cnt >= ndwarf_scnnames) diff --git a/libdrgn/elfutils/libdw/dwarf_decl_file.c b/libdrgn/elfutils/libdw/dwarf_decl_file.c index 5657132f4..d4aa0a18e 100644 --- a/libdrgn/elfutils/libdw/dwarf_decl_file.c +++ b/libdrgn/elfutils/libdw/dwarf_decl_file.c @@ -55,7 +55,7 @@ dwarf_decl_file (Dwarf_Die *die) } /* Get the array of source files for the CU. */ - struct Dwarf_CU *cu = die->cu; + struct Dwarf_CU *cu = attr_mem.cu; if (cu->lines == NULL) { Dwarf_Lines *lines; diff --git a/libdrgn/elfutils/libdw/dwarf_ranges.c b/libdrgn/elfutils/libdw/dwarf_ranges.c index f67d8a5a8..520f9ffe6 100644 --- a/libdrgn/elfutils/libdw/dwarf_ranges.c +++ b/libdrgn/elfutils/libdw/dwarf_ranges.c @@ -506,6 +506,11 @@ dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep, Dwarf_Attribute attr_mem; Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges, &attr_mem); + /* Note that above we use dwarf_attr, not dwarf_attr_integrate. + The only case where the ranges can come from another DIE + attribute are the split CU case. In that case we also have a + different CU to check against. But that is already set up + above using __libdw_find_split_unit. */ if (attr == NULL && is_cudie (die) && die->cu->unit_type == DW_UT_split_compile) diff --git a/libdrgn/elfutils/libdw/libdw.h b/libdrgn/elfutils/libdw/libdw.h index e20961be2..1a4e15a16 100644 --- a/libdrgn/elfutils/libdw/libdw.h +++ b/libdrgn/elfutils/libdw/libdw.h @@ -474,7 +474,14 @@ extern Dwarf_Attribute *dwarf_attr (Dwarf_Die *die, unsigned int search_name, extern int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name); /* These are the same as dwarf_attr and dwarf_hasattr, respectively, - but they resolve an indirect attribute through DW_AT_abstract_origin. */ + but they resolve an indirect attribute through + DW_AT_abstract_origin, DW_AT_specification or, if the DIE is a + top-level split CU, the skeleton DIE. Note that the attribute + might come from a DIE in a different CU (possibly from a different + Dwarf file). In that case all attribute information needs to be + resolved through the CU associated with the returned + Dwarf_Attribute. The dwarf_form functions already do this + automatically. */ extern Dwarf_Attribute *dwarf_attr_integrate (Dwarf_Die *die, unsigned int search_name, Dwarf_Attribute *result) diff --git a/libdrgn/elfutils/libdw/libdw.map b/libdrgn/elfutils/libdw/libdw.map index b2df2ba72..b4fa63631 100644 --- a/libdrgn/elfutils/libdw/libdw.map +++ b/libdrgn/elfutils/libdw/libdw.map @@ -370,7 +370,7 @@ ELFUTILS_0.177 { # presume that NULL is only returned on error (otherwise ELF_K_NONE). dwelf_elf_begin; } ELFUTILS_0.175; -ELFUTILS_0.179 { +ELFUTILS_0.180 { global: dwfl_attach_thread; dwfl_detach_thread; @@ -378,4 +378,4 @@ ELFUTILS_0.179 { dwfl_frame_dwarf_frame; dwfl_frame_register; dwfl_frame_eval_expr; -} ELFUTILS_0.178; +} ELFUTILS_0.177; diff --git a/libdrgn/elfutils/libdw/libdw_alloc.c b/libdrgn/elfutils/libdw/libdw_alloc.c index e0281a3df..b3e533434 100644 --- a/libdrgn/elfutils/libdw/libdw_alloc.c +++ b/libdrgn/elfutils/libdw/libdw_alloc.c @@ -87,6 +87,11 @@ __libdw_alloc_tail (Dwarf *dbg) if (result == NULL) { result = malloc (dbg->mem_default_size); + if (result == NULL) + { + pthread_rwlock_unlock (&dbg->mem_rwl); + dbg->oom_handler(); + } result->size = dbg->mem_default_size - offsetof (struct libdw_memblock, mem); result->remaining = result->size; diff --git a/libdrgn/elfutils/libdw/libdw_visit_scopes.c b/libdrgn/elfutils/libdw/libdw_visit_scopes.c index eb892e10a..7dfa5f6b8 100644 --- a/libdrgn/elfutils/libdw/libdw_visit_scopes.c +++ b/libdrgn/elfutils/libdw/libdw_visit_scopes.c @@ -125,8 +125,12 @@ walk_children (struct walk_children_state *state) Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&state->child.die, DW_AT_import, &attr_mem); + /* Some gcc -flto versions imported other top-level compile units, + skip those. */ if (INTUSE(dwarf_formref_die) (attr, &state->child.die) != NULL - && INTUSE(dwarf_child) (&state->child.die, &state->child.die) == 0) + && INTUSE(dwarf_tag) (&state->child.die) != DW_TAG_compile_unit + && (INTUSE(dwarf_child) (&state->child.die, &state->child.die) + == 0)) { /* Checks the given DIE hasn't been imported yet to prevent cycles. */ diff --git a/libdrgn/elfutils/libdwfl/ChangeLog b/libdrgn/elfutils/libdwfl/ChangeLog index 0b95490aa..3f9cd6659 100644 --- a/libdrgn/elfutils/libdwfl/ChangeLog +++ b/libdrgn/elfutils/libdwfl/ChangeLog @@ -1,3 +1,18 @@ +2020-04-30 Mark Wielaard + + * find-debuginfo.c (dwfl_standard_find_debuginfo): When mod->dw + is already set then try fetching debugaltlink. + +2020-04-25 Mark Wielaard + + * gzip.c (open_stream): Return DWFL_E_NOMEM instead of calling + zlib_fail. + +2020-04-16 Mark Wielaard + + * find-debuginfo.c (dwfl_standard_find_debuginfo): Initialize bits + to NULL. + 2020-01-24 Mark Wielaard * linux-kernel-modules.c (find_kernel_elf): Check release isn't NULL. diff --git a/libdrgn/elfutils/libdwfl/dwfl_frame.c b/libdrgn/elfutils/libdwfl/dwfl_frame.c index 80f2bc146..046f6c2ba 100644 --- a/libdrgn/elfutils/libdwfl/dwfl_frame.c +++ b/libdrgn/elfutils/libdwfl/dwfl_frame.c @@ -105,8 +105,7 @@ state_alloc (Dwfl_Thread *thread) state->frame = NULL; state->moderr = DWFL_E_NOERROR; state->frameerr = DWFL_E_NOERROR; - state->signal_frame = false; - state->initial_frame = true; + state->isactivation = true; state->pc_state = DWFL_FRAME_STATE_ERROR; memset (state->regs_set, 0, sizeof (state->regs_set)); thread->unwound = state; diff --git a/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c b/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c index 296c815b9..a955d995a 100644 --- a/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c +++ b/libdrgn/elfutils/libdwfl/dwfl_frame_pc.c @@ -39,26 +39,7 @@ dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) *pc = state->pc; ebl_normalize_pc (state->thread->process->ebl, pc); if (isactivation) - { - /* Bottom frame? */ - if (state->initial_frame) - *isactivation = true; - /* *ISACTIVATION is logical union of whether current or previous frame - state is SIGNAL_FRAME. */ - else if (state->signal_frame) - *isactivation = true; - else - { - /* If the previous frame has unwound unsuccessfully just silently do - not consider it could be a SIGNAL_FRAME. */ - __libdwfl_frame_unwind (state); - if (state->unwound == NULL - || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET) - *isactivation = false; - else - *isactivation = state->unwound->signal_frame; - } - } + *isactivation = state->isactivation; return true; } INTDEF (dwfl_frame_pc) diff --git a/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c b/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c index 83b1abef1..d013dc966 100644 --- a/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c +++ b/libdrgn/elfutils/libdwfl/dwfl_frame_regs.c @@ -38,7 +38,6 @@ dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg, { Dwfl_Frame *state = thread->unwound; assert (state && state->unwound == NULL); - assert (state->initial_frame); for (unsigned regno = firstreg; regno < firstreg + nregs; regno++) if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg])) { @@ -54,7 +53,6 @@ dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc) { Dwfl_Frame *state = thread->unwound; assert (state && state->unwound == NULL); - assert (state->initial_frame); state->pc = pc; state->pc_state = DWFL_FRAME_STATE_PC_SET; } diff --git a/libdrgn/elfutils/libdwfl/find-debuginfo.c b/libdrgn/elfutils/libdwfl/find-debuginfo.c index 408576454..4cfd0b8b2 100644 --- a/libdrgn/elfutils/libdwfl/find-debuginfo.c +++ b/libdrgn/elfutils/libdwfl/find-debuginfo.c @@ -357,7 +357,7 @@ dwfl_standard_find_debuginfo (Dwfl_Module *mod, { /* First try by build ID if we have one. If that succeeds or fails other than just by finding nothing, that's all we do. */ - const unsigned char *bits; + const unsigned char *bits = NULL; GElf_Addr vaddr; int bits_len; if ((bits_len = INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr)) > 0) @@ -398,8 +398,27 @@ dwfl_standard_find_debuginfo (Dwfl_Module *mod, free (canon); } - if (fd < 0 && bits_len > 0) - fd = __libdwfl_debuginfod_find_debuginfo (mod->dwfl, bits, bits_len); + /* Still nothing? Try if we can use the debuginfod client. + But note that we might be looking for the alt file. + We use the same trick as dwfl_build_id_find_debuginfo. + If the debug file (dw) is already set, then we must be + looking for the altfile. But we cannot use the actual + file/path name given as hint. We'll have to lookup the + alt file "build-id". Because the debuginfod client only + handles build-ids. */ + if (fd < 0) + { + if (mod->dw != NULL) + { + const char *altname; + bits_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, &altname, + (const void **) + &bits); + } + + if (bits_len > 0) + fd = __libdwfl_debuginfod_find_debuginfo (mod->dwfl, bits, bits_len); + } return fd; } diff --git a/libdrgn/elfutils/libdwfl/frame_unwind.c b/libdrgn/elfutils/libdwfl/frame_unwind.c index 13bff8fc6..4885caa13 100644 --- a/libdrgn/elfutils/libdwfl/frame_unwind.c +++ b/libdrgn/elfutils/libdwfl/frame_unwind.c @@ -58,6 +58,7 @@ dwfl_frame_register (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val) *val = state->regs[regno]; return true; } +INTDEF (dwfl_frame_register) bool internal_function @@ -526,8 +527,7 @@ new_unwound (Dwfl_Frame *state) unwound->frame = NULL; unwound->moderr = DWFL_E_NOERROR; unwound->frameerr = DWFL_E_NOERROR; - unwound->signal_frame = false; - unwound->initial_frame = false; + unwound->isactivation = false; unwound->pc_state = DWFL_FRAME_STATE_ERROR; memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); return unwound; @@ -542,7 +542,11 @@ static void handle_cfi (Dwfl_Frame *state, Dwarf_Frame *frame, Dwarf_Addr bias) { Dwfl_Frame *unwound = state->unwound; - unwound->signal_frame = frame->fde->cie->signal_frame; + if (frame->fde->cie->signal_frame) + { + state->isactivation = true; + unwound->isactivation = true; + } Dwfl_Thread *thread = state->thread; Dwfl_Process *process = thread->process; Ebl *ebl = process->ebl; @@ -704,14 +708,11 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) { if (state->unwound) return; - /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE - which would deadlock us. */ Dwarf_Addr pc; - bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL); + bool isactivation; + bool ok = INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); assert (ok); - /* Check whether this is the initial frame or a signal frame. - Then we need to unwind from the original, unadjusted PC. */ - if (! state->initial_frame && ! state->signal_frame) + if (! isactivation) pc--; Dwarf_Addr bias; Dwarf_Frame *frame = INTUSE(dwfl_frame_dwarf_frame) (state, &bias); @@ -732,7 +733,6 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) return; } state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; - // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. bool signal_frame = false; if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) { @@ -745,7 +745,11 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) return; } assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); - state->unwound->signal_frame = signal_frame; + if (signal_frame) + { + state->isactivation = true; + state->unwound->isactivation = true; + } } Dwfl_Module * @@ -756,7 +760,10 @@ dwfl_frame_module (Dwfl_Frame *state) if (state->moderr == DWFL_E_NOERROR) { Dwarf_Addr pc; - INTUSE(dwfl_frame_pc) (state, &pc, NULL); + bool isactivation; + INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); + if (! isactivation) + pc--; state->mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc); if (state->mod != NULL) return state->mod; @@ -765,6 +772,7 @@ dwfl_frame_module (Dwfl_Frame *state) __libdwfl_seterrno (state->moderr); return NULL; } +INTDEF (dwfl_frame_module) Dwarf_Frame * dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) @@ -780,7 +788,10 @@ dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) return NULL; } Dwarf_Addr pc; - INTUSE(dwfl_frame_pc) (state, &pc, NULL); + bool isactivation; + INTUSE(dwfl_frame_pc) (state, &pc, &isactivation); + if (! isactivation) + pc--; Dwarf_CFI *cfi = INTUSE(dwfl_module_eh_cfi) (state->mod, &state->bias); if (cfi @@ -802,6 +813,7 @@ dwfl_frame_dwarf_frame (Dwfl_Frame *state, Dwarf_Addr *bias) *bias = state->bias; return state->frame; } +INTDEF (dwfl_frame_dwarf_frame) bool dwfl_frame_eval_expr (Dwfl_Frame *state, const Dwarf_Op *ops, size_t nops, diff --git a/libdrgn/elfutils/libdwfl/gzip.c b/libdrgn/elfutils/libdwfl/gzip.c index 043d0b6ed..e9988cc2b 100644 --- a/libdrgn/elfutils/libdwfl/gzip.c +++ b/libdrgn/elfutils/libdwfl/gzip.c @@ -153,7 +153,7 @@ open_stream (int fd, off_t start_offset, struct unzip_state *state) if (unlikely (state->zf == NULL)) { close (d); - return zlib_fail (state, Z (MEM_ERROR)); + return DWFL_E_NOMEM; } /* From here on, zlib will close D. */ diff --git a/libdrgn/elfutils/libdwfl/libdwflP.h b/libdrgn/elfutils/libdwfl/libdwflP.h index eab003e66..613ccf016 100644 --- a/libdrgn/elfutils/libdwfl/libdwflP.h +++ b/libdrgn/elfutils/libdwfl/libdwflP.h @@ -261,8 +261,7 @@ struct Dwfl_Frame Dwfl_Error moderr; /* Error trying to get frame. */ Dwfl_Error frameerr; - bool signal_frame : 1; - bool initial_frame : 1; + bool isactivation; enum { /* This structure is still being initialized or there was an error @@ -775,12 +774,15 @@ INTDECL (dwfl_pid) INTDECL (dwfl_thread_dwfl) INTDECL (dwfl_thread_tid) INTDECL (dwfl_frame_thread) +INTDECL (dwfl_frame_module) +INTDECL (dwfl_frame_dwarf_frame) INTDECL (dwfl_thread_state_registers) INTDECL (dwfl_thread_state_register_pc) INTDECL (dwfl_getthread_frames) INTDECL (dwfl_getthreads) INTDECL (dwfl_thread_getframes) INTDECL (dwfl_frame_pc) +INTDECL (dwfl_frame_register) /* Leading arguments standard to callbacks passed a Dwfl_Module. */ #define MODCB_ARGS(mod) (mod), &(mod)->userdata, (mod)->name, (mod)->low_addr diff --git a/libdrgn/elfutils/libebl/ChangeLog b/libdrgn/elfutils/libebl/ChangeLog index b32873104..90cf97281 100644 --- a/libdrgn/elfutils/libebl/ChangeLog +++ b/libdrgn/elfutils/libebl/ChangeLog @@ -1,3 +1,8 @@ +2020-04-17 Mark Wielaard + + * eblopenbackend.c (default_debugscn_p): Handle .gnu.debuglto_ + prefix. + 2020-02-08 Mark Wielaard * eblsegmenttypename.c (ebl_segment_type_name): Handle diff --git a/libdrgn/elfutils/libebl/eblopenbackend.c b/libdrgn/elfutils/libebl/eblopenbackend.c index 210b47e88..4ebde45f2 100644 --- a/libdrgn/elfutils/libebl/eblopenbackend.c +++ b/libdrgn/elfutils/libebl/eblopenbackend.c @@ -621,7 +621,9 @@ default_debugscn_p (const char *name) for (size_t cnt = 0; cnt < ndwarf_scn_names; ++cnt) if (strcmp (name, dwarf_scn_names[cnt]) == 0 || (strncmp (name, ".zdebug", strlen (".zdebug")) == 0 - && strcmp (&name[2], &dwarf_scn_names[cnt][1]) == 0)) + && strcmp (&name[2], &dwarf_scn_names[cnt][1]) == 0) + || (strncmp (name, ".gnu.debuglto_", strlen (".gnu.debuglto_")) == 0 + && strcmp (&name[14], dwarf_scn_names[cnt]) == 0)) return true; return false; diff --git a/libdrgn/elfutils/libelf/ChangeLog b/libdrgn/elfutils/libelf/ChangeLog index dde6c81df..56f5354c5 100644 --- a/libdrgn/elfutils/libelf/ChangeLog +++ b/libdrgn/elfutils/libelf/ChangeLog @@ -1,3 +1,18 @@ +2020-04-25 Mark Wielaard + + * elf_compress.c (__libelf_compress): Remove free (out_buf). + +2020-03-18 Omar Sandoval + + * elf_getphdrnum.c (__elf_getphdrnum_rdlock): Call + __elf{32,64}_getshdr_rdlock if the shdr is not cached. + +2019-03-20 Matthias Maennich + + * elf_compress.c (__libelf_compress): Always call deflate_cleanup + in failure path. Call deflateEnd only once. + (__libelf_decompress): Call inflateEnd only once. + 2019-06-18 Mark Wielaard * common.h (allocate_elf): Use int64_t instead of off_t for offset. diff --git a/libdrgn/elfutils/libelf/elf_compress.c b/libdrgn/elfutils/libelf/elf_compress.c index 244467b5e..e5d3d2e09 100644 --- a/libdrgn/elfutils/libelf/elf_compress.c +++ b/libdrgn/elfutils/libelf/elf_compress.c @@ -113,9 +113,8 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data, int zrc = deflateInit (&z, Z_BEST_COMPRESSION); if (zrc != Z_OK) { - free (out_buf); __libelf_seterrno (ELF_E_COMPRESS_ERROR); - return NULL; + return deflate_cleanup(NULL, NULL); } Elf_Data cdata; @@ -197,13 +196,13 @@ __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data, } while (flush != Z_FINISH); /* More data blocks. */ - zrc = deflateEnd (&z); - if (zrc != Z_OK) + if (zrc != Z_STREAM_END) { __libelf_seterrno (ELF_E_COMPRESS_ERROR); return deflate_cleanup (NULL, NULL); } + deflateEnd (&z); *new_size = used; return out_buf; } @@ -251,16 +250,15 @@ __libelf_decompress (void *buf_in, size_t size_in, size_t size_out) } zrc = inflateReset (&z); } - if (likely (zrc == Z_OK)) - zrc = inflateEnd (&z); if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0)) { free (buf_out); + buf_out = NULL; __libelf_seterrno (ELF_E_DECOMPRESS_ERROR); - return NULL; } + inflateEnd(&z); return buf_out; } diff --git a/libdrgn/elfutils/libelf/elf_getphdrnum.c b/libdrgn/elfutils/libelf/elf_getphdrnum.c index f91cba981..53617dfc7 100644 --- a/libdrgn/elfutils/libelf/elf_getphdrnum.c +++ b/libdrgn/elfutils/libelf/elf_getphdrnum.c @@ -63,15 +63,23 @@ __elf_getphdrnum_rdlock (Elf *elf, size_t *dst) if (elf->class == ELFCLASS32) { - if (likely (scns->cnt > 0 - && elf->state.elf32.scns.data[0].shdr.e32 != NULL)) - *dst = scns->data[0].shdr.e32->sh_info; + if (likely (scns->cnt > 0)) + { + Elf_Scn *scn = &elf->state.elf32.scns.data[0]; + Elf32_Shdr *shdr = scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn); + if (shdr) + *dst = shdr->sh_info; + } } else { - if (likely (scns->cnt > 0 - && elf->state.elf64.scns.data[0].shdr.e64 != NULL)) - *dst = scns->data[0].shdr.e64->sh_info; + if (likely (scns->cnt > 0)) + { + Elf_Scn *scn = &elf->state.elf64.scns.data[0]; + Elf64_Shdr *shdr = scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn); + if (shdr) + *dst = shdr->sh_info; + } } } diff --git a/libdrgn/elfutils/po/ChangeLog b/libdrgn/elfutils/po/ChangeLog index 884b16668..61c97fde4 100644 --- a/libdrgn/elfutils/po/ChangeLog +++ b/libdrgn/elfutils/po/ChangeLog @@ -1,3 +1,7 @@ +2020-03-30 Mark Wielaard + + * *.po: Update for 0.179. + 2019-11-26 Mark Wielaard * *.po: Update for 0.178. diff --git a/libdrgn/elfutils/po/de.po b/libdrgn/elfutils/po/de.po index a9b6897ab..528c8df55 100644 --- a/libdrgn/elfutils/po/de.po +++ b/libdrgn/elfutils/po/de.po @@ -11,7 +11,7 @@ msgid "" msgstr "" "Project-Id-Version: elfutils VERSION\n" "Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n" -"POT-Creation-Date: 2019-11-26 09:48+0100\n" +"POT-Creation-Date: 2020-03-30 12:56+0200\n" "PO-Revision-Date: 2009-06-29 15:15+0200\n" "Last-Translator: Michael Münch \n" "Language-Team: German\n" @@ -533,7 +533,7 @@ msgstr "Kein Backend" #: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:77 #: libebl/eblobjnotetypename.c:109 libebl/eblobjnotetypename.c:130 #: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83 -#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:79 +#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:85 msgid "" msgstr "" @@ -1671,14 +1671,14 @@ msgid "" "section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n" msgstr "" -#: src/elflint.c:610 src/elflint.c:1494 src/elflint.c:1545 src/elflint.c:1651 -#: src/elflint.c:1987 src/elflint.c:2313 src/elflint.c:2932 src/elflint.c:3095 -#: src/elflint.c:3243 src/elflint.c:3433 src/elflint.c:4431 +#: src/elflint.c:610 src/elflint.c:1498 src/elflint.c:1549 src/elflint.c:1655 +#: src/elflint.c:1991 src/elflint.c:2317 src/elflint.c:2936 src/elflint.c:3099 +#: src/elflint.c:3247 src/elflint.c:3437 src/elflint.c:4435 #, c-format msgid "section [%2d] '%s': cannot get section data\n" msgstr "" -#: src/elflint.c:623 src/elflint.c:1658 +#: src/elflint.c:623 src/elflint.c:1662 #, c-format msgid "" "section [%2d] '%s': referenced as string table for section [%2d] '%s' but " @@ -1697,40 +1697,47 @@ msgstr "" msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n" msgstr "" -#: src/elflint.c:667 +#: src/elflint.c:662 +#, c-format +msgid "" +"section [%2u] '%s': number of local entries in 'st_info' larger than table " +"size\n" +msgstr "" + +#: src/elflint.c:671 #, c-format msgid "section [%2d] '%s': cannot get symbol %d: %s\n" msgstr "" -#: src/elflint.c:672 src/elflint.c:675 src/elflint.c:678 src/elflint.c:681 -#: src/elflint.c:684 src/elflint.c:687 +#: src/elflint.c:676 src/elflint.c:679 src/elflint.c:682 src/elflint.c:685 +#: src/elflint.c:688 src/elflint.c:691 #, c-format msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n" msgstr "" -#: src/elflint.c:690 +#: src/elflint.c:694 #, c-format msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n" msgstr "" -#: src/elflint.c:700 +#: src/elflint.c:704 #, c-format msgid "section [%2d] '%s': cannot get symbol %zu: %s\n" msgstr "" -#: src/elflint.c:709 +#: src/elflint.c:713 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid name value\n" msgstr "" -#: src/elflint.c:724 +#: src/elflint.c:728 #, c-format msgid "" "section [%2d] '%s': symbol %zu: too large section index but no extended " "section index section\n" msgstr "" -#: src/elflint.c:730 +#: src/elflint.c:734 #, c-format msgid "" "section [%2d] '%s': symbol %zu: XINDEX used for index which would fit in " @@ -1738,116 +1745,116 @@ msgid "" msgstr "" #. || sym->st_shndx > SHN_HIRESERVE always false -#: src/elflint.c:742 +#: src/elflint.c:746 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid section index\n" msgstr "" -#: src/elflint.c:750 +#: src/elflint.c:754 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown type\n" msgstr "" -#: src/elflint.c:756 +#: src/elflint.c:760 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown symbol binding\n" msgstr "" -#: src/elflint.c:761 +#: src/elflint.c:765 #, c-format msgid "section [%2d] '%s': symbol %zu: unique symbol not of object type\n" msgstr "" -#: src/elflint.c:769 +#: src/elflint.c:773 #, c-format msgid "" "section [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n" msgstr "" -#: src/elflint.c:773 +#: src/elflint.c:777 #, c-format msgid "section [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n" msgstr "" -#: src/elflint.c:777 +#: src/elflint.c:781 #, c-format msgid "" "section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n" msgstr "" -#: src/elflint.c:828 +#: src/elflint.c:832 #, c-format msgid "section [%2d] '%s': symbol %zu: st_value out of bounds\n" msgstr "" -#: src/elflint.c:834 src/elflint.c:859 src/elflint.c:908 +#: src/elflint.c:838 src/elflint.c:863 src/elflint.c:912 #, c-format msgid "" "section [%2d] '%s': symbol %zu does not fit completely in referenced section " "[%2d] '%s'\n" msgstr "" -#: src/elflint.c:843 +#: src/elflint.c:847 #, c-format msgid "" "section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have " "SHF_TLS flag set\n" msgstr "" -#: src/elflint.c:853 src/elflint.c:901 +#: src/elflint.c:857 src/elflint.c:905 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section " "[%2d] '%s'\n" msgstr "" -#: src/elflint.c:880 +#: src/elflint.c:884 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n" msgstr "" -#: src/elflint.c:886 +#: src/elflint.c:890 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program " "header entry\n" msgstr "" -#: src/elflint.c:894 +#: src/elflint.c:898 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] " "'%s'\n" msgstr "" -#: src/elflint.c:921 +#: src/elflint.c:925 #, c-format msgid "" "section [%2d] '%s': symbol %zu: local symbol outside range described in " "sh_info\n" msgstr "" -#: src/elflint.c:928 +#: src/elflint.c:932 #, c-format msgid "" "section [%2d] '%s': symbol %zu: non-local symbol outside range described in " "sh_info\n" msgstr "" -#: src/elflint.c:935 +#: src/elflint.c:939 #, c-format msgid "section [%2d] '%s': symbol %zu: non-local section symbol\n" msgstr "" -#: src/elflint.c:985 +#: src/elflint.c:989 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section " "[%2d]\n" msgstr "" -#: src/elflint.c:992 +#: src/elflint.c:996 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] " @@ -1857,1367 +1864,1367 @@ msgstr "" #. This test is more strict than the psABIs which #. usually allow the symbol to be in the middle of #. the .got section, allowing negative offsets. -#: src/elflint.c:1008 +#: src/elflint.c:1012 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %# does not " "match %s section address %#\n" msgstr "" -#: src/elflint.c:1015 +#: src/elflint.c:1019 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size % does not " "match %s section size %\n" msgstr "" -#: src/elflint.c:1023 +#: src/elflint.c:1027 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got " "section\n" msgstr "" -#: src/elflint.c:1039 +#: src/elflint.c:1043 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC_ symbol value %# does not match dynamic " "segment address %#\n" msgstr "" -#: src/elflint.c:1046 +#: src/elflint.c:1050 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC symbol size % does not match dynamic " "segment size %\n" msgstr "" -#: src/elflint.c:1059 +#: src/elflint.c:1063 #, c-format msgid "" "section [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-" "default visibility\n" msgstr "" -#: src/elflint.c:1063 +#: src/elflint.c:1067 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown bit set in st_other\n" msgstr "" -#: src/elflint.c:1101 +#: src/elflint.c:1105 #, fuzzy, c-format msgid "section [%2d] '%s': cannot get section data.\n" msgstr "konnte Abschnittsdaten nicht holen: %s" -#: src/elflint.c:1117 +#: src/elflint.c:1121 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n" msgstr "" -#: src/elflint.c:1128 src/elflint.c:1181 +#: src/elflint.c:1132 src/elflint.c:1185 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n" msgstr "" -#: src/elflint.c:1153 src/elflint.c:1206 +#: src/elflint.c:1157 src/elflint.c:1210 #, c-format msgid "" "section [%2d] '%s': relative relocations after index %d as specified by " "DT_RELCOUNT\n" msgstr "" -#: src/elflint.c:1159 src/elflint.c:1212 +#: src/elflint.c:1163 src/elflint.c:1216 #, c-format msgid "" "section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT " "specified %d relative relocations\n" msgstr "" -#: src/elflint.c:1171 +#: src/elflint.c:1175 #, c-format msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n" msgstr "" -#: src/elflint.c:1254 +#: src/elflint.c:1258 #, c-format msgid "section [%2d] '%s': invalid destination section index\n" msgstr "" -#: src/elflint.c:1266 +#: src/elflint.c:1270 #, c-format msgid "section [%2d] '%s': invalid destination section type\n" msgstr "" -#: src/elflint.c:1274 +#: src/elflint.c:1278 #, c-format msgid "section [%2d] '%s': sh_info should be zero\n" msgstr "" -#: src/elflint.c:1282 +#: src/elflint.c:1286 #, fuzzy, c-format msgid "" "section [%2d] '%s': no relocations for merge-able string sections possible\n" msgstr "konnte Abschnittsdaten nicht holen: %s" -#: src/elflint.c:1290 +#: src/elflint.c:1294 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n" msgstr "" -#: src/elflint.c:1350 +#: src/elflint.c:1354 #, c-format msgid "text relocation flag set but there is no read-only segment\n" msgstr "" -#: src/elflint.c:1377 +#: src/elflint.c:1381 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid type\n" msgstr "" -#: src/elflint.c:1385 +#: src/elflint.c:1389 #, c-format msgid "" "section [%2d] '%s': relocation %zu: relocation type invalid for the file " "type\n" msgstr "" -#: src/elflint.c:1393 +#: src/elflint.c:1397 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n" msgstr "" -#: src/elflint.c:1411 +#: src/elflint.c:1415 #, c-format msgid "" "section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can " "be used with %s\n" msgstr "" -#: src/elflint.c:1428 +#: src/elflint.c:1432 #, c-format msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n" msgstr "" -#: src/elflint.c:1443 +#: src/elflint.c:1447 #, c-format msgid "" "section [%2d] '%s': relocation %zu: copy relocation against symbol of type " "%s\n" msgstr "" -#: src/elflint.c:1464 +#: src/elflint.c:1468 #, c-format msgid "" "section [%2d] '%s': relocation %zu: read-only section modified but text " "relocation flag not set\n" msgstr "" -#: src/elflint.c:1479 +#: src/elflint.c:1483 #, c-format msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n" msgstr "" -#: src/elflint.c:1519 src/elflint.c:1570 +#: src/elflint.c:1523 src/elflint.c:1574 #, c-format msgid "section [%2d] '%s': cannot get relocation %zu: %s\n" msgstr "" -#: src/elflint.c:1646 +#: src/elflint.c:1650 #, c-format msgid "more than one dynamic section present\n" msgstr "" -#: src/elflint.c:1664 +#: src/elflint.c:1668 #, c-format msgid "" "section [%2d]: referenced as string table for section [%2d] '%s' but section " "link value is invalid\n" msgstr "" -#: src/elflint.c:1672 +#: src/elflint.c:1676 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n" msgstr "" -#: src/elflint.c:1677 src/elflint.c:1966 +#: src/elflint.c:1681 src/elflint.c:1970 #, c-format msgid "section [%2d] '%s': sh_info not zero\n" msgstr "" -#: src/elflint.c:1687 +#: src/elflint.c:1691 #, c-format msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n" msgstr "" -#: src/elflint.c:1695 +#: src/elflint.c:1699 #, c-format msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n" msgstr "" -#: src/elflint.c:1702 +#: src/elflint.c:1706 #, c-format msgid "section [%2d] '%s': entry %zu: unknown tag\n" msgstr "" -#: src/elflint.c:1713 +#: src/elflint.c:1717 #, c-format msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n" msgstr "" -#: src/elflint.c:1723 +#: src/elflint.c:1727 #, c-format msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n" msgstr "" -#: src/elflint.c:1741 +#: src/elflint.c:1745 #, c-format msgid "" "section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n" msgstr "" -#: src/elflint.c:1754 +#: src/elflint.c:1758 #, c-format msgid "" "section [%2d] '%s': entry %zu: pointer does not match address of section " "[%2d] '%s' referenced by sh_link\n" msgstr "" -#: src/elflint.c:1797 +#: src/elflint.c:1801 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must point into loaded segment\n" msgstr "" -#: src/elflint.c:1812 +#: src/elflint.c:1816 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must be valid offset in section " "[%2d] '%s'\n" msgstr "" -#: src/elflint.c:1832 src/elflint.c:1860 +#: src/elflint.c:1836 src/elflint.c:1864 #, c-format msgid "section [%2d] '%s': contains %s entry but not %s\n" msgstr "" -#: src/elflint.c:1844 +#: src/elflint.c:1848 #, c-format msgid "section [%2d] '%s': mandatory tag %s not present\n" msgstr "" -#: src/elflint.c:1853 +#: src/elflint.c:1857 #, c-format msgid "section [%2d] '%s': no hash section present\n" msgstr "" -#: src/elflint.c:1868 src/elflint.c:1875 +#: src/elflint.c:1872 src/elflint.c:1879 #, c-format msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n" msgstr "" -#: src/elflint.c:1885 src/elflint.c:1889 +#: src/elflint.c:1889 src/elflint.c:1893 #, c-format msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n" msgstr "" -#: src/elflint.c:1895 +#: src/elflint.c:1899 #, c-format msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n" msgstr "" -#: src/elflint.c:1906 src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 +#: src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 src/elflint.c:1922 #, c-format msgid "section [%2d] '%s': %s tag missing in prelinked executable\n" msgstr "" -#: src/elflint.c:1930 +#: src/elflint.c:1934 #, c-format msgid "" "section [%2d] '%s': only relocatable files can have extended section index\n" msgstr "" -#: src/elflint.c:1940 +#: src/elflint.c:1944 #, c-format msgid "" "section [%2d] '%s': extended section index section not for symbol table\n" msgstr "" -#: src/elflint.c:1944 +#: src/elflint.c:1948 #, c-format msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n" msgstr "" -#: src/elflint.c:1949 +#: src/elflint.c:1953 #, c-format msgid "cannot get data for symbol section\n" msgstr "" -#: src/elflint.c:1952 +#: src/elflint.c:1956 #, c-format msgid "section [%2d] '%s': entry size does not match Elf32_Word\n" msgstr "" -#: src/elflint.c:1961 +#: src/elflint.c:1965 #, c-format msgid "section [%2d] '%s': extended index table too small for symbol table\n" msgstr "" -#: src/elflint.c:1976 +#: src/elflint.c:1980 #, c-format msgid "" "section [%2d] '%s': extended section index in section [%2zu] '%s' refers to " "same symbol table\n" msgstr "" -#: src/elflint.c:1994 +#: src/elflint.c:1998 #, c-format msgid "symbol 0 should have zero extended section index\n" msgstr "" -#: src/elflint.c:2006 +#: src/elflint.c:2010 #, c-format msgid "cannot get data for symbol %zu\n" msgstr "" -#: src/elflint.c:2011 +#: src/elflint.c:2015 #, c-format msgid "extended section index is % but symbol index is not XINDEX\n" msgstr "" -#: src/elflint.c:2028 src/elflint.c:2085 +#: src/elflint.c:2032 src/elflint.c:2089 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n" msgstr "" -#: src/elflint.c:2042 src/elflint.c:2099 +#: src/elflint.c:2046 src/elflint.c:2103 #, c-format msgid "section [%2d] '%s': chain array too large\n" msgstr "" -#: src/elflint.c:2056 src/elflint.c:2113 +#: src/elflint.c:2060 src/elflint.c:2117 #, c-format msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n" msgstr "" -#: src/elflint.c:2066 +#: src/elflint.c:2070 #, c-format msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n" msgstr "" -#: src/elflint.c:2123 +#: src/elflint.c:2127 #, c-format msgid "section [%2d] '%s': hash chain reference % out of bounds\n" msgstr "" -#: src/elflint.c:2136 +#: src/elflint.c:2140 #, c-format msgid "section [%2d] '%s': not enough data\n" msgstr "" -#: src/elflint.c:2148 +#: src/elflint.c:2152 #, c-format msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n" msgstr "" -#: src/elflint.c:2164 +#: src/elflint.c:2168 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected at " "least %ld)\n" msgstr "" -#: src/elflint.c:2173 +#: src/elflint.c:2177 #, c-format msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n" msgstr "" -#: src/elflint.c:2207 +#: src/elflint.c:2211 #, c-format msgid "" "section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n" msgstr "" -#: src/elflint.c:2228 +#: src/elflint.c:2232 #, c-format msgid "" "section [%2d] '%s': symbol %u referenced in chain for bucket %zu is " "undefined\n" msgstr "" -#: src/elflint.c:2241 +#: src/elflint.c:2245 #, c-format msgid "" "section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n" msgstr "" -#: src/elflint.c:2250 +#: src/elflint.c:2254 #, c-format msgid "" "section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n" msgstr "" -#: src/elflint.c:2280 +#: src/elflint.c:2284 #, c-format msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n" msgstr "" -#: src/elflint.c:2285 +#: src/elflint.c:2289 #, c-format msgid "" "section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n" msgstr "" -#: src/elflint.c:2291 +#: src/elflint.c:2295 #, c-format msgid "section [%2d] '%s': bitmask does not match names in the hash table\n" msgstr "" -#: src/elflint.c:2304 +#: src/elflint.c:2308 #, c-format msgid "section [%2d] '%s': relocatable files cannot have hash tables\n" msgstr "" -#: src/elflint.c:2322 +#: src/elflint.c:2326 #, c-format msgid "section [%2d] '%s': hash table not for dynamic symbol table\n" msgstr "" -#: src/elflint.c:2326 +#: src/elflint.c:2330 #, c-format msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n" msgstr "" -#: src/elflint.c:2336 +#: src/elflint.c:2340 #, c-format msgid "section [%2d] '%s': hash table entry size incorrect\n" msgstr "" -#: src/elflint.c:2341 +#: src/elflint.c:2345 #, c-format msgid "section [%2d] '%s': not marked to be allocated\n" msgstr "" -#: src/elflint.c:2346 +#: src/elflint.c:2350 #, c-format msgid "" "section [%2d] '%s': hash table has not even room for initial administrative " "entries\n" msgstr "" -#: src/elflint.c:2395 +#: src/elflint.c:2399 #, c-format msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n" msgstr "" -#: src/elflint.c:2419 src/elflint.c:2484 src/elflint.c:2519 +#: src/elflint.c:2423 src/elflint.c:2488 src/elflint.c:2523 #, c-format msgid "hash section [%2zu] '%s' does not contain enough data\n" msgstr "" -#: src/elflint.c:2440 +#: src/elflint.c:2444 #, c-format msgid "hash section [%2zu] '%s' has zero bit mask words\n" msgstr "" -#: src/elflint.c:2451 src/elflint.c:2495 src/elflint.c:2532 +#: src/elflint.c:2455 src/elflint.c:2499 src/elflint.c:2536 #, c-format msgid "hash section [%2zu] '%s' uses too much data\n" msgstr "" -#: src/elflint.c:2466 +#: src/elflint.c:2470 #, c-format msgid "" "hash section [%2zu] '%s' invalid symbol index % (max_nsyms: " "%, nentries: %\n" msgstr "" -#: src/elflint.c:2553 +#: src/elflint.c:2557 #, c-format msgid "hash section [%2zu] '%s' invalid sh_entsize\n" msgstr "" -#: src/elflint.c:2563 src/elflint.c:2567 +#: src/elflint.c:2567 src/elflint.c:2571 #, c-format msgid "section [%2zu] '%s': reference to symbol index 0\n" msgstr "" -#: src/elflint.c:2574 +#: src/elflint.c:2578 #, c-format msgid "" "symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash " "table in [%2zu] '%s'\n" msgstr "" -#: src/elflint.c:2586 +#: src/elflint.c:2590 #, c-format msgid "" "symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash " "table in [%2zu] '%s'\n" msgstr "" -#: src/elflint.c:2602 +#: src/elflint.c:2606 #, c-format msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n" msgstr "" -#: src/elflint.c:2622 +#: src/elflint.c:2626 #, c-format msgid "" "section [%2d] '%s': section groups only allowed in relocatable object files\n" msgstr "" -#: src/elflint.c:2633 +#: src/elflint.c:2637 #, c-format msgid "section [%2d] '%s': cannot get symbol table: %s\n" msgstr "" -#: src/elflint.c:2638 +#: src/elflint.c:2642 #, c-format msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n" msgstr "" -#: src/elflint.c:2644 +#: src/elflint.c:2648 #, c-format msgid "section [%2d] '%s': invalid symbol index in sh_info\n" msgstr "" -#: src/elflint.c:2649 +#: src/elflint.c:2653 #, c-format msgid "section [%2d] '%s': sh_flags not zero\n" msgstr "" -#: src/elflint.c:2656 +#: src/elflint.c:2660 #, c-format msgid "section [%2d] '%s': cannot get symbol for signature\n" msgstr "" -#: src/elflint.c:2660 +#: src/elflint.c:2664 #, c-format msgid "section [%2d] '%s': cannot get symbol name for signature\n" msgstr "" -#: src/elflint.c:2665 +#: src/elflint.c:2669 #, c-format msgid "section [%2d] '%s': signature symbol cannot be empty string\n" msgstr "" -#: src/elflint.c:2671 +#: src/elflint.c:2675 #, c-format msgid "section [%2d] '%s': sh_flags not set correctly\n" msgstr "" -#: src/elflint.c:2677 +#: src/elflint.c:2681 #, c-format msgid "section [%2d] '%s': cannot get data: %s\n" msgstr "" -#: src/elflint.c:2686 +#: src/elflint.c:2690 #, c-format msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n" msgstr "" -#: src/elflint.c:2692 +#: src/elflint.c:2696 #, c-format msgid "section [%2d] '%s': section group without flags word\n" msgstr "" -#: src/elflint.c:2700 +#: src/elflint.c:2704 #, c-format msgid "section [%2d] '%s': section group without member\n" msgstr "" -#: src/elflint.c:2704 +#: src/elflint.c:2708 #, c-format msgid "section [%2d] '%s': section group with only one member\n" msgstr "" -#: src/elflint.c:2715 +#: src/elflint.c:2719 #, c-format msgid "section [%2d] '%s': unknown section group flags\n" msgstr "" -#: src/elflint.c:2727 +#: src/elflint.c:2731 #, fuzzy, c-format msgid "section [%2d] '%s': section index %zu out of range\n" msgstr "konnte Abschnittsdaten nicht holen: %s" -#: src/elflint.c:2736 +#: src/elflint.c:2740 #, c-format msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n" msgstr "" -#: src/elflint.c:2743 +#: src/elflint.c:2747 #, c-format msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n" msgstr "" -#: src/elflint.c:2749 +#: src/elflint.c:2753 #, c-format msgid "" "section [%2d] '%s': element %zu references section [%2d] '%s' without " "SHF_GROUP flag set\n" msgstr "" -#: src/elflint.c:2756 +#: src/elflint.c:2760 #, c-format msgid "section [%2d] '%s' is contained in more than one section group\n" msgstr "" -#: src/elflint.c:2946 +#: src/elflint.c:2950 #, c-format msgid "" "section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no " "dynamic symbol table\n" msgstr "" -#: src/elflint.c:2958 +#: src/elflint.c:2962 #, c-format msgid "" "section [%2d] '%s' has different number of entries than symbol table [%2d] " "'%s'\n" msgstr "" -#: src/elflint.c:2974 +#: src/elflint.c:2978 #, c-format msgid "section [%2d] '%s': symbol %d: cannot read version data\n" msgstr "" -#: src/elflint.c:2990 +#: src/elflint.c:2994 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n" msgstr "" -#: src/elflint.c:2998 +#: src/elflint.c:3002 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with version\n" msgstr "" -#: src/elflint.c:3012 +#: src/elflint.c:3016 #, c-format msgid "section [%2d] '%s': symbol %d: invalid version index %d\n" msgstr "" -#: src/elflint.c:3017 +#: src/elflint.c:3021 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for defined version\n" msgstr "" -#: src/elflint.c:3027 +#: src/elflint.c:3031 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for requested version\n" msgstr "" -#: src/elflint.c:3080 +#: src/elflint.c:3084 #, c-format msgid "more than one version reference section present\n" msgstr "" -#: src/elflint.c:3088 src/elflint.c:3235 +#: src/elflint.c:3092 src/elflint.c:3239 #, c-format msgid "section [%2d] '%s': sh_link does not link to string table\n" msgstr "" -#: src/elflint.c:3113 src/elflint.c:3289 +#: src/elflint.c:3117 src/elflint.c:3293 #, c-format msgid "section [%2d] '%s': entry %d has wrong version %d\n" msgstr "" -#: src/elflint.c:3120 src/elflint.c:3296 +#: src/elflint.c:3124 src/elflint.c:3300 #, c-format msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n" msgstr "" -#: src/elflint.c:3130 +#: src/elflint.c:3134 #, c-format msgid "section [%2d] '%s': entry %d has invalid file reference\n" msgstr "" -#: src/elflint.c:3138 +#: src/elflint.c:3142 #, c-format msgid "section [%2d] '%s': entry %d references unknown dependency\n" msgstr "" -#: src/elflint.c:3150 +#: src/elflint.c:3154 #, c-format msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n" msgstr "" -#: src/elflint.c:3158 +#: src/elflint.c:3162 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has invalid name " "reference\n" msgstr "" -#: src/elflint.c:3167 +#: src/elflint.c:3171 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: " "%#x, expected %#x\n" msgstr "" -#: src/elflint.c:3176 +#: src/elflint.c:3180 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version " "name '%s'\n" msgstr "" -#: src/elflint.c:3187 +#: src/elflint.c:3191 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n" msgstr "" -#: src/elflint.c:3204 src/elflint.c:3380 +#: src/elflint.c:3208 src/elflint.c:3384 #, c-format msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n" msgstr "" -#: src/elflint.c:3212 src/elflint.c:3388 +#: src/elflint.c:3216 src/elflint.c:3392 #, c-format msgid "" "section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says " "there are more entries\n" msgstr "" -#: src/elflint.c:3227 +#: src/elflint.c:3231 #, c-format msgid "more than one version definition section present\n" msgstr "" -#: src/elflint.c:3274 +#: src/elflint.c:3278 #, c-format msgid "section [%2d] '%s': more than one BASE definition\n" msgstr "" -#: src/elflint.c:3278 +#: src/elflint.c:3282 #, c-format msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n" msgstr "" -#: src/elflint.c:3284 +#: src/elflint.c:3288 #, c-format msgid "section [%2d] '%s': entry %d has unknown flag\n" msgstr "" -#: src/elflint.c:3311 +#: src/elflint.c:3315 #, c-format msgid "section [%2d] '%s': entry %d has invalid name reference\n" msgstr "" -#: src/elflint.c:3318 +#: src/elflint.c:3322 #, c-format msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n" msgstr "" -#: src/elflint.c:3326 +#: src/elflint.c:3330 #, c-format msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n" msgstr "" -#: src/elflint.c:3346 +#: src/elflint.c:3350 #, c-format msgid "" "section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n" msgstr "" -#: src/elflint.c:3363 +#: src/elflint.c:3367 #, c-format msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n" msgstr "" -#: src/elflint.c:3396 +#: src/elflint.c:3400 #, c-format msgid "section [%2d] '%s': no BASE definition\n" msgstr "" -#: src/elflint.c:3412 +#: src/elflint.c:3416 #, c-format msgid "section [%2d] '%s': unknown parent version '%s'\n" msgstr "" -#: src/elflint.c:3425 +#: src/elflint.c:3429 #, c-format msgid "section [%2d] '%s': empty object attributes section\n" msgstr "" -#: src/elflint.c:3446 +#: src/elflint.c:3450 #, c-format msgid "section [%2d] '%s': unrecognized attribute format\n" msgstr "" -#: src/elflint.c:3462 +#: src/elflint.c:3466 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute section\n" msgstr "" -#: src/elflint.c:3471 +#: src/elflint.c:3475 #, c-format msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n" msgstr "" -#: src/elflint.c:3483 +#: src/elflint.c:3487 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n" msgstr "" -#: src/elflint.c:3500 +#: src/elflint.c:3504 #, c-format msgid "" "section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n" msgstr "" -#: src/elflint.c:3509 +#: src/elflint.c:3513 #, c-format msgid "section [%2d] '%s': offset %zu: truncated attribute section\n" msgstr "" -#: src/elflint.c:3518 +#: src/elflint.c:3522 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute subsection\n" msgstr "" -#: src/elflint.c:3533 +#: src/elflint.c:3537 #, c-format msgid "" "section [%2d] '%s': offset %zu: invalid length in attribute subsection\n" msgstr "" #. Tag_File -#: src/elflint.c:3544 +#: src/elflint.c:3548 #, c-format msgid "" "section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n" msgstr "" -#: src/elflint.c:3562 +#: src/elflint.c:3566 #, c-format msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n" msgstr "" -#: src/elflint.c:3573 +#: src/elflint.c:3577 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n" msgstr "" -#: src/elflint.c:3586 +#: src/elflint.c:3590 #, c-format msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n" msgstr "" -#: src/elflint.c:3590 +#: src/elflint.c:3594 #, c-format msgid "" "section [%2d] '%s': offset %zu: unrecognized %s attribute value %\n" msgstr "" -#: src/elflint.c:3600 +#: src/elflint.c:3604 #, c-format msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n" msgstr "" -#: src/elflint.c:3606 +#: src/elflint.c:3610 #, c-format msgid "" "section [%2d] '%s': offset %zu: extra bytes after last attribute section\n" msgstr "" -#: src/elflint.c:3695 +#: src/elflint.c:3699 #, c-format msgid "cannot get section header of zeroth section\n" msgstr "" -#: src/elflint.c:3699 +#: src/elflint.c:3703 #, c-format msgid "zeroth section has nonzero name\n" msgstr "" -#: src/elflint.c:3701 +#: src/elflint.c:3705 #, c-format msgid "zeroth section has nonzero type\n" msgstr "" -#: src/elflint.c:3703 +#: src/elflint.c:3707 #, c-format msgid "zeroth section has nonzero flags\n" msgstr "" -#: src/elflint.c:3705 +#: src/elflint.c:3709 #, c-format msgid "zeroth section has nonzero address\n" msgstr "" -#: src/elflint.c:3707 +#: src/elflint.c:3711 #, c-format msgid "zeroth section has nonzero offset\n" msgstr "" -#: src/elflint.c:3709 +#: src/elflint.c:3713 #, c-format msgid "zeroth section has nonzero align value\n" msgstr "" -#: src/elflint.c:3711 +#: src/elflint.c:3715 #, c-format msgid "zeroth section has nonzero entry size value\n" msgstr "" -#: src/elflint.c:3714 +#: src/elflint.c:3718 #, c-format msgid "" "zeroth section has nonzero size value while ELF header has nonzero shnum " "value\n" msgstr "" -#: src/elflint.c:3718 +#: src/elflint.c:3722 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " "overflow in shstrndx\n" msgstr "" -#: src/elflint.c:3722 +#: src/elflint.c:3726 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " "overflow in phnum\n" msgstr "" -#: src/elflint.c:3740 +#: src/elflint.c:3744 #, c-format msgid "cannot get section header for section [%2zu] '%s': %s\n" msgstr "" -#: src/elflint.c:3749 +#: src/elflint.c:3753 #, c-format msgid "section [%2zu]: invalid name\n" msgstr "" -#: src/elflint.c:3776 +#: src/elflint.c:3780 #, c-format msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n" msgstr "" -#: src/elflint.c:3794 +#: src/elflint.c:3798 #, c-format msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n" msgstr "" -#: src/elflint.c:3812 +#: src/elflint.c:3816 #, c-format msgid "" "section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n" msgstr "" -#: src/elflint.c:3830 +#: src/elflint.c:3834 #, c-format msgid "section [%2zu] '%s' present in object file\n" msgstr "" -#: src/elflint.c:3836 src/elflint.c:3868 +#: src/elflint.c:3840 src/elflint.c:3872 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n" msgstr "" -#: src/elflint.c:3841 src/elflint.c:3873 +#: src/elflint.c:3845 src/elflint.c:3877 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable " "segments\n" msgstr "" -#: src/elflint.c:3849 +#: src/elflint.c:3853 #, c-format msgid "" "section [%2zu] '%s' is extension section index table in non-object file\n" msgstr "" -#: src/elflint.c:3892 +#: src/elflint.c:3896 #, c-format msgid "section [%2zu] '%s': size not multiple of entry size\n" msgstr "" -#: src/elflint.c:3897 +#: src/elflint.c:3901 #, c-format msgid "cannot get section header\n" msgstr "" -#: src/elflint.c:3907 +#: src/elflint.c:3911 #, c-format msgid "section [%2zu] '%s' has unsupported type %d\n" msgstr "" -#: src/elflint.c:3922 +#: src/elflint.c:3926 #, c-format msgid "" "section [%2zu] '%s' contains invalid processor-specific flag(s) %#\n" msgstr "" -#: src/elflint.c:3929 +#: src/elflint.c:3933 #, c-format msgid "section [%2zu] '%s' contains unknown flag(s) %#\n" msgstr "" -#: src/elflint.c:3937 +#: src/elflint.c:3941 #, c-format msgid "section [%2zu] '%s': thread-local data sections address not zero\n" msgstr "" -#: src/elflint.c:3947 +#: src/elflint.c:3951 #, fuzzy, c-format msgid "section [%2zu] '%s': allocated section cannot be compressed\n" msgstr "konnte Abschnittsdaten nicht holen: %s" -#: src/elflint.c:3952 +#: src/elflint.c:3956 #, fuzzy, c-format msgid "section [%2zu] '%s': nobits section cannot be compressed\n" msgstr "konnte Abschnittsdaten nicht holen: %s" -#: src/elflint.c:3958 +#: src/elflint.c:3962 #, c-format msgid "" "section [%2zu] '%s': compressed section with no compression header: %s\n" msgstr "" -#: src/elflint.c:3964 +#: src/elflint.c:3968 #, c-format msgid "section [%2zu] '%s': invalid section reference in link value\n" msgstr "" -#: src/elflint.c:3969 +#: src/elflint.c:3973 #, c-format msgid "section [%2zu] '%s': invalid section reference in info value\n" msgstr "" -#: src/elflint.c:3976 +#: src/elflint.c:3980 #, c-format msgid "section [%2zu] '%s': strings flag set without merge flag\n" msgstr "" -#: src/elflint.c:3981 +#: src/elflint.c:3985 #, c-format msgid "section [%2zu] '%s': merge flag set but entry size is zero\n" msgstr "" -#: src/elflint.c:4000 +#: src/elflint.c:4004 #, c-format msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n" msgstr "" -#: src/elflint.c:4009 +#: src/elflint.c:4013 #, c-format msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n" msgstr "" -#: src/elflint.c:4016 +#: src/elflint.c:4020 #, c-format msgid "section [%2zu] '%s' is both executable and writable\n" msgstr "" -#: src/elflint.c:4047 +#: src/elflint.c:4051 #, c-format msgid "" "section [%2zu] '%s' not fully contained in segment of program header entry " "%d\n" msgstr "" -#: src/elflint.c:4057 +#: src/elflint.c:4061 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " "program header entry %d\n" msgstr "" -#: src/elflint.c:4083 +#: src/elflint.c:4087 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " "program header entry %d and file contents is non-zero\n" msgstr "" -#: src/elflint.c:4094 +#: src/elflint.c:4098 #, c-format msgid "" "section [%2zu] '%s' has not type NOBITS but is not read from the file in " "segment of program header entry %d\n" msgstr "" -#: src/elflint.c:4105 +#: src/elflint.c:4109 #, c-format msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n" msgstr "" -#: src/elflint.c:4115 +#: src/elflint.c:4119 #, c-format msgid "section [%2zu] '%s' is writable in unwritable segment %d\n" msgstr "" -#: src/elflint.c:4125 +#: src/elflint.c:4129 #, c-format msgid "" "section [%2zu] '%s': alloc flag set but section not in any loaded segment\n" msgstr "" -#: src/elflint.c:4131 +#: src/elflint.c:4135 #, c-format msgid "" "section [%2zu] '%s': ELF header says this is the section header string table " "but type is not SHT_TYPE\n" msgstr "" -#: src/elflint.c:4139 +#: src/elflint.c:4143 #, c-format msgid "" "section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n" msgstr "" -#: src/elflint.c:4190 +#: src/elflint.c:4194 #, c-format msgid "more than one version symbol table present\n" msgstr "" -#: src/elflint.c:4213 +#: src/elflint.c:4217 #, c-format msgid "INTERP program header entry but no .interp section\n" msgstr "" -#: src/elflint.c:4224 +#: src/elflint.c:4228 #, c-format msgid "" "loadable segment [%u] is executable but contains no executable sections\n" msgstr "" -#: src/elflint.c:4230 +#: src/elflint.c:4234 #, c-format msgid "loadable segment [%u] is writable but contains no writable sections\n" msgstr "" -#: src/elflint.c:4241 +#: src/elflint.c:4245 #, c-format msgid "" "no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section " "exist\n" msgstr "" -#: src/elflint.c:4254 +#: src/elflint.c:4258 #, c-format msgid "duplicate version index %d\n" msgstr "" -#: src/elflint.c:4268 +#: src/elflint.c:4272 #, c-format msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n" msgstr "" -#: src/elflint.c:4317 +#: src/elflint.c:4321 #, c-format msgid "phdr[%d]: unknown core file note type % at offset %\n" msgstr "" -#: src/elflint.c:4321 +#: src/elflint.c:4325 #, c-format msgid "" "section [%2d] '%s': unknown core file note type % at offset %zu\n" msgstr "" -#: src/elflint.c:4370 +#: src/elflint.c:4374 #, c-format msgid "" "phdr[%d]: unknown object file note type % with owner name '%s' at " "offset %zu\n" msgstr "" -#: src/elflint.c:4375 +#: src/elflint.c:4379 #, c-format msgid "" "section [%2d] '%s': unknown object file note type % with owner name " "'%s' at offset %zu\n" msgstr "" -#: src/elflint.c:4394 +#: src/elflint.c:4398 #, c-format msgid "phdr[%d]: no note entries defined for the type of file\n" msgstr "" -#: src/elflint.c:4414 +#: src/elflint.c:4418 #, c-format msgid "phdr[%d]: cannot get content of note section: %s\n" msgstr "" -#: src/elflint.c:4417 +#: src/elflint.c:4421 #, c-format msgid "phdr[%d]: extra % bytes after last note\n" msgstr "" -#: src/elflint.c:4438 +#: src/elflint.c:4442 #, c-format msgid "section [%2d] '%s': no note entries defined for the type of file\n" msgstr "" -#: src/elflint.c:4445 +#: src/elflint.c:4449 #, c-format msgid "section [%2d] '%s': cannot get content of note section\n" msgstr "" -#: src/elflint.c:4448 +#: src/elflint.c:4452 #, c-format msgid "section [%2d] '%s': extra % bytes after last note\n" msgstr "" -#: src/elflint.c:4466 +#: src/elflint.c:4470 #, c-format msgid "" "only executables, shared objects, and core files can have program headers\n" msgstr "" -#: src/elflint.c:4481 +#: src/elflint.c:4485 #, c-format msgid "cannot get program header entry %d: %s\n" msgstr "" -#: src/elflint.c:4490 +#: src/elflint.c:4499 #, c-format msgid "program header entry %d: unknown program header entry type %#\n" msgstr "" -#: src/elflint.c:4501 +#: src/elflint.c:4510 #, c-format msgid "more than one INTERP entry in program header\n" msgstr "" -#: src/elflint.c:4509 +#: src/elflint.c:4518 #, c-format msgid "more than one TLS entry in program header\n" msgstr "" -#: src/elflint.c:4516 +#: src/elflint.c:4525 #, c-format msgid "static executable cannot have dynamic sections\n" msgstr "" -#: src/elflint.c:4530 +#: src/elflint.c:4539 #, c-format msgid "dynamic section reference in program header has wrong offset\n" msgstr "" -#: src/elflint.c:4533 +#: src/elflint.c:4542 #, c-format msgid "dynamic section size mismatch in program and section header\n" msgstr "" -#: src/elflint.c:4543 +#: src/elflint.c:4552 #, c-format msgid "more than one GNU_RELRO entry in program header\n" msgstr "" -#: src/elflint.c:4564 +#: src/elflint.c:4573 #, c-format msgid "loadable segment GNU_RELRO applies to is not writable\n" msgstr "" -#: src/elflint.c:4575 +#: src/elflint.c:4584 #, c-format msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n" msgstr "" -#: src/elflint.c:4582 +#: src/elflint.c:4591 #, c-format msgid "" "GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n" msgstr "" -#: src/elflint.c:4591 src/elflint.c:4614 +#: src/elflint.c:4600 src/elflint.c:4623 #, c-format msgid "%s segment not contained in a loaded segment\n" msgstr "" -#: src/elflint.c:4620 +#: src/elflint.c:4629 #, c-format msgid "program header offset in ELF header and PHDR entry do not match" msgstr "" -#: src/elflint.c:4647 +#: src/elflint.c:4656 #, c-format msgid "call frame search table reference in program header has wrong offset\n" msgstr "" -#: src/elflint.c:4650 +#: src/elflint.c:4659 #, c-format msgid "call frame search table size mismatch in program and section header\n" msgstr "" -#: src/elflint.c:4663 +#: src/elflint.c:4672 #, c-format msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n" msgstr "" -#: src/elflint.c:4671 +#: src/elflint.c:4680 #, c-format msgid "call frame search table must be allocated\n" msgstr "" -#: src/elflint.c:4674 +#: src/elflint.c:4683 #, c-format msgid "section [%2zu] '%s' must be allocated\n" msgstr "" -#: src/elflint.c:4678 +#: src/elflint.c:4687 #, c-format msgid "call frame search table must not be writable\n" msgstr "" -#: src/elflint.c:4681 +#: src/elflint.c:4690 #, c-format msgid "section [%2zu] '%s' must not be writable\n" msgstr "" -#: src/elflint.c:4686 +#: src/elflint.c:4695 #, c-format msgid "call frame search table must not be executable\n" msgstr "" -#: src/elflint.c:4689 +#: src/elflint.c:4698 #, c-format msgid "section [%2zu] '%s' must not be executable\n" msgstr "" -#: src/elflint.c:4700 +#: src/elflint.c:4709 #, c-format msgid "program header entry %d: file size greater than memory size\n" msgstr "" -#: src/elflint.c:4707 +#: src/elflint.c:4716 #, c-format msgid "program header entry %d: alignment not a power of 2\n" msgstr "" -#: src/elflint.c:4710 +#: src/elflint.c:4719 #, c-format msgid "" "program header entry %d: file offset and virtual address not module of " "alignment\n" msgstr "" -#: src/elflint.c:4723 +#: src/elflint.c:4732 #, c-format msgid "" "executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME " "program header entry" msgstr "" -#: src/elflint.c:4757 +#: src/elflint.c:4766 #, c-format msgid "cannot read ELF header: %s\n" msgstr "" -#: src/elflint.c:4783 +#: src/elflint.c:4792 #, c-format msgid "text relocation flag set but not needed\n" msgstr "" diff --git a/libdrgn/elfutils/po/es.po b/libdrgn/elfutils/po/es.po index 0d32a5de2..ffb877be9 100644 --- a/libdrgn/elfutils/po/es.po +++ b/libdrgn/elfutils/po/es.po @@ -10,7 +10,7 @@ msgid "" msgstr "" "Project-Id-Version: elfutils.master.es\n" "Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n" -"POT-Creation-Date: 2019-11-26 09:48+0100\n" +"POT-Creation-Date: 2020-03-30 12:56+0200\n" "PO-Revision-Date: 2011-01-10 15:17-0300\n" "Last-Translator: Claudio Rodrigo Pereyra Diaz \n" @@ -531,7 +531,7 @@ msgstr "No hay segundo plano (Backend)" #: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:77 #: libebl/eblobjnotetypename.c:109 libebl/eblobjnotetypename.c:130 #: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83 -#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:79 +#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:85 msgid "" msgstr "" @@ -1690,14 +1690,14 @@ msgstr "" "sección [%2d] '%s': el grupo de sección [%2zu] '%s' no precede al miembro de " "grupo\n" -#: src/elflint.c:610 src/elflint.c:1494 src/elflint.c:1545 src/elflint.c:1651 -#: src/elflint.c:1987 src/elflint.c:2313 src/elflint.c:2932 src/elflint.c:3095 -#: src/elflint.c:3243 src/elflint.c:3433 src/elflint.c:4431 +#: src/elflint.c:610 src/elflint.c:1498 src/elflint.c:1549 src/elflint.c:1655 +#: src/elflint.c:1991 src/elflint.c:2317 src/elflint.c:2936 src/elflint.c:3099 +#: src/elflint.c:3247 src/elflint.c:3437 src/elflint.c:4435 #, c-format msgid "section [%2d] '%s': cannot get section data\n" msgstr "Sección [%2d] '%s': No se pueden obtener datos de sección\n" -#: src/elflint.c:623 src/elflint.c:1658 +#: src/elflint.c:623 src/elflint.c:1662 #, c-format msgid "" "section [%2d] '%s': referenced as string table for section [%2d] '%s' but " @@ -1721,33 +1721,42 @@ msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n" msgstr "" "sección [%2u] '%s': el tamaño de la entrada no coincide con ElfXX_Sym\n" -#: src/elflint.c:667 +#: src/elflint.c:662 +#, fuzzy, c-format +msgid "" +"section [%2u] '%s': number of local entries in 'st_info' larger than table " +"size\n" +msgstr "" +"Sección [%2d] '%s': no hay entradas de nota definidas para el tipo de " +"archivo\n" + +#: src/elflint.c:671 #, c-format msgid "section [%2d] '%s': cannot get symbol %d: %s\n" msgstr "Sección [%2d] '%s': no se puede obtener símbolo %d: %s\n" -#: src/elflint.c:672 src/elflint.c:675 src/elflint.c:678 src/elflint.c:681 -#: src/elflint.c:684 src/elflint.c:687 +#: src/elflint.c:676 src/elflint.c:679 src/elflint.c:682 src/elflint.c:685 +#: src/elflint.c:688 src/elflint.c:691 #, c-format msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n" msgstr "Sección [%2d] '%s': '%s' en la entrada zeroth no es cero\n" -#: src/elflint.c:690 +#: src/elflint.c:694 #, c-format msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n" msgstr "sección [%2d] '%s': XINDEX en la entrada zeroth no es cero\n" -#: src/elflint.c:700 +#: src/elflint.c:704 #, c-format msgid "section [%2d] '%s': cannot get symbol %zu: %s\n" msgstr "sección [%2d] '%s': no es posible obtener el símbolo %zu: %s\n" -#: src/elflint.c:709 +#: src/elflint.c:713 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid name value\n" msgstr "sección [%2d] '%s': símbolo %zu: valor de nombre inválido\n" -#: src/elflint.c:724 +#: src/elflint.c:728 #, c-format msgid "" "section [%2d] '%s': symbol %zu: too large section index but no extended " @@ -1756,7 +1765,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: el índice de sección es demasiado extenso, " "pero no la sección extendida de la sección de índice\n" -#: src/elflint.c:730 +#: src/elflint.c:734 #, c-format msgid "" "section [%2d] '%s': symbol %zu: XINDEX used for index which would fit in " @@ -1766,27 +1775,27 @@ msgstr "" "caber en st_shndx (%)\n" #. || sym->st_shndx > SHN_HIRESERVE always false -#: src/elflint.c:742 +#: src/elflint.c:746 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid section index\n" msgstr "sección [%2d] '%s': símbolo %zu: índice de sección inválido\n" -#: src/elflint.c:750 +#: src/elflint.c:754 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown type\n" msgstr "sección [%2d] '%s': símbolo %zu: tipo desconocido\n" -#: src/elflint.c:756 +#: src/elflint.c:760 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown symbol binding\n" msgstr "sección [%2d] '%s': símbolo %zu: asociación de símbolo desconocida\n" -#: src/elflint.c:761 +#: src/elflint.c:765 #, c-format msgid "section [%2d] '%s': symbol %zu: unique symbol not of object type\n" msgstr "Sección [%2d] '%s': símbolo %zu: símbolo único no de tipo de objeto\n" -#: src/elflint.c:769 +#: src/elflint.c:773 #, c-format msgid "" "section [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n" @@ -1794,25 +1803,25 @@ msgstr "" "sección [%2d] '%s': símbolo %zu: COMMON solo es permitido en archivos " "realojables\n" -#: src/elflint.c:773 +#: src/elflint.c:777 #, c-format msgid "section [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n" msgstr "" "Sección [%2d] '%s': símbolo %zu: símbolos locales COMMON no tienen sentido\n" -#: src/elflint.c:777 +#: src/elflint.c:781 #, c-format msgid "" "section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n" msgstr "" "Sección [%2d] '%s': símbolo %zu: función en sección COMMON no tiene sentido\n" -#: src/elflint.c:828 +#: src/elflint.c:832 #, c-format msgid "section [%2d] '%s': symbol %zu: st_value out of bounds\n" msgstr "sección [%2d] '%s': símbolo %zu: st_value fuera de límites\n" -#: src/elflint.c:834 src/elflint.c:859 src/elflint.c:908 +#: src/elflint.c:838 src/elflint.c:863 src/elflint.c:912 #, c-format msgid "" "section [%2d] '%s': symbol %zu does not fit completely in referenced section " @@ -1821,7 +1830,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu no se ajusta totalmente en la sección [%2d] " "'%s'\n" -#: src/elflint.c:843 +#: src/elflint.c:847 #, c-format msgid "" "section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have " @@ -1830,7 +1839,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: sección de referencia [%2d] '%s' no tiene " "establecida bandera SHF_TLS\n" -#: src/elflint.c:853 src/elflint.c:901 +#: src/elflint.c:857 src/elflint.c:905 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section " @@ -1839,7 +1848,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: st_value fuera de límites de sección de " "referencia [%2d] '%s'\n" -#: src/elflint.c:880 +#: src/elflint.c:884 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n" @@ -1847,7 +1856,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: símbolo TLS, pero no hay entrada de " "programa TLS\n" -#: src/elflint.c:886 +#: src/elflint.c:890 #, fuzzy, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program " @@ -1856,7 +1865,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: símbolo TLS, pero no hay entrada de " "programa TLS\n" -#: src/elflint.c:894 +#: src/elflint.c:898 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] " @@ -1865,7 +1874,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: st_value falta sección de referencia [%2d] " "'%s'\n" -#: src/elflint.c:921 +#: src/elflint.c:925 #, c-format msgid "" "section [%2d] '%s': symbol %zu: local symbol outside range described in " @@ -1874,7 +1883,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: símbolo local fuera del rango descrito en " "sh_info\n" -#: src/elflint.c:928 +#: src/elflint.c:932 #, c-format msgid "" "section [%2d] '%s': symbol %zu: non-local symbol outside range described in " @@ -1883,12 +1892,12 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: símbolo non-local fuera del rango descrito " "en sh_info\n" -#: src/elflint.c:935 +#: src/elflint.c:939 #, c-format msgid "section [%2d] '%s': symbol %zu: non-local section symbol\n" msgstr "Sección [%2d] '%s': símbolo %zu: símbolo de sección non-local\n" -#: src/elflint.c:985 +#: src/elflint.c:989 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section " @@ -1897,7 +1906,7 @@ msgstr "" "Sección [%2d] '%s': símbolo _GLOBAL_OFFSET_TABLE_ se refiere a sección " "errada [%2d]\n" -#: src/elflint.c:992 +#: src/elflint.c:996 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] " @@ -1909,7 +1918,7 @@ msgstr "" #. This test is more strict than the psABIs which #. usually allow the symbol to be in the middle of #. the .got section, allowing negative offsets. -#: src/elflint.c:1008 +#: src/elflint.c:1012 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %# does not " @@ -1918,7 +1927,7 @@ msgstr "" "Sección [%2d] '%s': valor del símbolo _GLOBAL_OFFSET_TABLE_ %# no " "coincide con dirección de sección %s %#\n" -#: src/elflint.c:1015 +#: src/elflint.c:1019 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size % does not " @@ -1927,7 +1936,7 @@ msgstr "" "Sección [%2d] '%s': tamaño de símbolo _GLOBAL_OFFSET_TABLE_ % no " "coincide con tamaño de sección %s %\n" -#: src/elflint.c:1023 +#: src/elflint.c:1027 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got " @@ -1936,7 +1945,7 @@ msgstr "" "Sección [%2d] '%s': símbolo _GLOBAL_OFFSET_TABLE_ presente, pero no. sección " "got\n" -#: src/elflint.c:1039 +#: src/elflint.c:1043 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC_ symbol value %# does not match dynamic " @@ -1945,7 +1954,7 @@ msgstr "" "sección [%2d] '%s': Valor de símbolo _DYNAMIC_ %# no coincide con la " "dirección de segmento%#\n" -#: src/elflint.c:1046 +#: src/elflint.c:1050 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC symbol size % does not match dynamic " @@ -1954,7 +1963,7 @@ msgstr "" "Sección [%2d] '%s': tamaño de símbolo _DYNAMIC % no coincide con " "tamaño de segmento %\n" -#: src/elflint.c:1059 +#: src/elflint.c:1063 #, c-format msgid "" "section [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-" @@ -1963,29 +1972,29 @@ msgstr "" "Sección [%2d] '%s': símbolo %zu: símbolo en tabla de símbolos dinámicos sin " "visibilidad predeterminada\n" -#: src/elflint.c:1063 +#: src/elflint.c:1067 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown bit set in st_other\n" msgstr "" "Sección [%2d] '%s': símbolo %zu: bit desconocido establecido en st_other\n" -#: src/elflint.c:1101 +#: src/elflint.c:1105 #, fuzzy, c-format msgid "section [%2d] '%s': cannot get section data.\n" msgstr "Sección [%2d] '%s': No se pueden obtener datos de sección\n" -#: src/elflint.c:1117 +#: src/elflint.c:1121 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n" msgstr "Sección [%2d] '%s': DT_RELCOUNT utilizada para esta sección RELA\n" -#: src/elflint.c:1128 src/elflint.c:1181 +#: src/elflint.c:1132 src/elflint.c:1185 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n" msgstr "" "Sección [%2d] '%s': valor DT_RELCOUNT %d demasiado alto para esta sección\n" -#: src/elflint.c:1153 src/elflint.c:1206 +#: src/elflint.c:1157 src/elflint.c:1210 #, c-format msgid "" "section [%2d] '%s': relative relocations after index %d as specified by " @@ -1994,7 +2003,7 @@ msgstr "" "Sección [%2d] '%s': reubicaciones relativas después de que el %d de índice " "haya sido especificado por DT_RELCOUNT\n" -#: src/elflint.c:1159 src/elflint.c:1212 +#: src/elflint.c:1163 src/elflint.c:1216 #, c-format msgid "" "section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT " @@ -2003,50 +2012,50 @@ msgstr "" "Sección [%2d] '%s': reubicación no-relativa en %zu de índice; DT_RELCOUNT " "especificado %d reubicaciones relativas\n" -#: src/elflint.c:1171 +#: src/elflint.c:1175 #, c-format msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n" msgstr "sección [%2d] '%s': DT_RELACOUNT utilizado para esta sección REL\n" -#: src/elflint.c:1254 +#: src/elflint.c:1258 #, c-format msgid "section [%2d] '%s': invalid destination section index\n" msgstr "Sección [%2d] '%s': índice de sección de destino inválido\n" -#: src/elflint.c:1266 +#: src/elflint.c:1270 #, c-format msgid "section [%2d] '%s': invalid destination section type\n" msgstr "Sección [%2d] '%s': tipo de sección de destino inválido\n" -#: src/elflint.c:1274 +#: src/elflint.c:1278 #, c-format msgid "section [%2d] '%s': sh_info should be zero\n" msgstr "Sección [%2d] '%s': sh_info debe ser cero\n" -#: src/elflint.c:1282 +#: src/elflint.c:1286 #, fuzzy, c-format msgid "" "section [%2d] '%s': no relocations for merge-able string sections possible\n" msgstr "" "Sección [%2d] '%s': no reubicaciones para secciones de fusión posibles\n" -#: src/elflint.c:1290 +#: src/elflint.c:1294 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n" msgstr "" "Sección [%2d] '%s': tamaño de entrada de sección no coincide con ElfXX_Rela\n" -#: src/elflint.c:1350 +#: src/elflint.c:1354 #, c-format msgid "text relocation flag set but there is no read-only segment\n" msgstr "Reubicación de bandera pero no hay segmento de sólo lectura\n" -#: src/elflint.c:1377 +#: src/elflint.c:1381 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid type\n" msgstr "Sección [%2d] '%s': reubicación %zu: tipo inválido\n" -#: src/elflint.c:1385 +#: src/elflint.c:1389 #, c-format msgid "" "section [%2d] '%s': relocation %zu: relocation type invalid for the file " @@ -2055,12 +2064,12 @@ msgstr "" "Sección [%2d] '%s': reubicación %zu: tipo de reubicación inválido para el " "tipo de archivo\n" -#: src/elflint.c:1393 +#: src/elflint.c:1397 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n" msgstr "Sección [%2d] '%s': reubicación %zu: índice de símbolo inválido\n" -#: src/elflint.c:1411 +#: src/elflint.c:1415 #, c-format msgid "" "section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can " @@ -2069,12 +2078,12 @@ msgstr "" "Sección [%2d] '%s': reubicación %zu: sólo el símbolo '_GLOBAL_OFFSET_TABLE_' " "puede utilizarse con %s\n" -#: src/elflint.c:1428 +#: src/elflint.c:1432 #, c-format msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n" msgstr "Sección [%2d] '%s': reubicación %zu: compensación fuera de límites\n" -#: src/elflint.c:1443 +#: src/elflint.c:1447 #, c-format msgid "" "section [%2d] '%s': relocation %zu: copy relocation against symbol of type " @@ -2083,7 +2092,7 @@ msgstr "" "Sección [%2d] '%s': reubicación %zu: reubicación de copia con símbolo de " "tipo %s\n" -#: src/elflint.c:1464 +#: src/elflint.c:1468 #, c-format msgid "" "section [%2d] '%s': relocation %zu: read-only section modified but text " @@ -2092,24 +2101,24 @@ msgstr "" "Sección [%2d] '%s': reubicación %zu: sección de sólo-lectura modificada, " "pero no se estableció bandera de reubicación\n" -#: src/elflint.c:1479 +#: src/elflint.c:1483 #, c-format msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n" msgstr "" "Sección [%2d] '%s': las reubicaciones se hacen con datos cargados y " "descargados\n" -#: src/elflint.c:1519 src/elflint.c:1570 +#: src/elflint.c:1523 src/elflint.c:1574 #, c-format msgid "section [%2d] '%s': cannot get relocation %zu: %s\n" msgstr "Sección [%2d] '%s': no puede obtener reubicación %zu: %s\n" -#: src/elflint.c:1646 +#: src/elflint.c:1650 #, c-format msgid "more than one dynamic section present\n" msgstr "más de una sección dinámica presente\n" -#: src/elflint.c:1664 +#: src/elflint.c:1668 #, fuzzy, c-format msgid "" "section [%2d]: referenced as string table for section [%2d] '%s' but section " @@ -2118,44 +2127,44 @@ msgstr "" "sección [%2d] '%s': nombrado como una tabla de cadena para la sección [%2d] " "'%s' pero el tipo no es SHT_STRTAB\n" -#: src/elflint.c:1672 +#: src/elflint.c:1676 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n" msgstr "" "Sección [%2d] '%s': tamaño de entrada de sección no coincide con ElfXX_Dyn\n" -#: src/elflint.c:1677 src/elflint.c:1966 +#: src/elflint.c:1681 src/elflint.c:1970 #, c-format msgid "section [%2d] '%s': sh_info not zero\n" msgstr "Sección [%2d] '%s': sh_info no es cero\n" -#: src/elflint.c:1687 +#: src/elflint.c:1691 #, c-format msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n" msgstr "" "Sección [%2d] '%s': no puede obtener entrada de sección dinámica %zu: %s\n" -#: src/elflint.c:1695 +#: src/elflint.c:1699 #, c-format msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n" msgstr "Sección [%2d] '%s': entradas non-DT_NULL siguen a la entrada DT_NULL\n" -#: src/elflint.c:1702 +#: src/elflint.c:1706 #, c-format msgid "section [%2d] '%s': entry %zu: unknown tag\n" msgstr "Sección [%2d] '%s': entrada %zu: etiqueta desconocida\n" -#: src/elflint.c:1713 +#: src/elflint.c:1717 #, c-format msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n" msgstr "Sección [%2d] '%s': entrada %zu: más de una entrada con etiqueta %s\n" -#: src/elflint.c:1723 +#: src/elflint.c:1727 #, c-format msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n" msgstr "Sección [%2d] '%s': entrada %zu: nivel 2 etiqueta %s utilizada\n" -#: src/elflint.c:1741 +#: src/elflint.c:1745 #, c-format msgid "" "section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n" @@ -2163,7 +2172,7 @@ msgstr "" "Sección [%2d] '%s': entrada %zu: el valor DT_PLTREL debe ser DT_REL or " "DT_RELA\n" -#: src/elflint.c:1754 +#: src/elflint.c:1758 #, c-format msgid "" "section [%2d] '%s': entry %zu: pointer does not match address of section " @@ -2172,14 +2181,14 @@ msgstr "" "Sección [%2d] '%s': entrada %zu: puntero no coincide con dirección de " "sección [%2d] '%s' al que hace referencia sh_link\n" -#: src/elflint.c:1797 +#: src/elflint.c:1801 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must point into loaded segment\n" msgstr "" "Sección [%2d] '%s': entrada %zu: valor %s debe apuntar en segmento cargado\n" -#: src/elflint.c:1812 +#: src/elflint.c:1816 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must be valid offset in section " @@ -2188,46 +2197,46 @@ msgstr "" "sección [%2d] '%s': entrada %zu: valor %s debe ser compensación válida en " "sección [%2d] '%s'\n" -#: src/elflint.c:1832 src/elflint.c:1860 +#: src/elflint.c:1836 src/elflint.c:1864 #, c-format msgid "section [%2d] '%s': contains %s entry but not %s\n" msgstr "Sección [%2d] '%s': contiene entrada %s pero no %s\n" -#: src/elflint.c:1844 +#: src/elflint.c:1848 #, c-format msgid "section [%2d] '%s': mandatory tag %s not present\n" msgstr "Sección [%2d] '%s': etiqueta obligatoria %s no está presente\n" -#: src/elflint.c:1853 +#: src/elflint.c:1857 #, c-format msgid "section [%2d] '%s': no hash section present\n" msgstr "Sección [%2d] '%s': no hay sección de dispersión presente\n" -#: src/elflint.c:1868 src/elflint.c:1875 +#: src/elflint.c:1872 src/elflint.c:1879 #, c-format msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n" msgstr "Sección [%2d] '%s': no todas las %s, %s, y %s están presentes\n" -#: src/elflint.c:1885 src/elflint.c:1889 +#: src/elflint.c:1889 src/elflint.c:1893 #, c-format msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n" msgstr "" "Sección [%2d] '%s': etiqueta %s faltante en DSO marcada durante el pre-" "enlace\n" -#: src/elflint.c:1895 +#: src/elflint.c:1899 #, c-format msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n" msgstr "" "Sección [%2d] '%s': archivo no-DSO marcado como dependencia durante el pre-" "enlace\n" -#: src/elflint.c:1906 src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 +#: src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 src/elflint.c:1922 #, c-format msgid "section [%2d] '%s': %s tag missing in prelinked executable\n" msgstr "Sección [%2d] '%s': etiqueta %s faltante en pre-enlace ejecutable\n" -#: src/elflint.c:1930 +#: src/elflint.c:1934 #, c-format msgid "" "section [%2d] '%s': only relocatable files can have extended section index\n" @@ -2235,37 +2244,37 @@ msgstr "" "Sección [%2d] '%s': sólo los archivos reubicables pueden tener índice de " "sección extendido\n" -#: src/elflint.c:1940 +#: src/elflint.c:1944 #, c-format msgid "" "section [%2d] '%s': extended section index section not for symbol table\n" msgstr "" "Sección [%2d] '%s': índice de sección extendido no para tabla de símbolos\n" -#: src/elflint.c:1944 +#: src/elflint.c:1948 #, fuzzy, c-format msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n" msgstr "" "Sección [%2d] '%s': índice de sección extendido no para tabla de símbolos\n" -#: src/elflint.c:1949 +#: src/elflint.c:1953 #, c-format msgid "cannot get data for symbol section\n" msgstr "no se puede obtener sección para símbolos\n" -#: src/elflint.c:1952 +#: src/elflint.c:1956 #, c-format msgid "section [%2d] '%s': entry size does not match Elf32_Word\n" msgstr "Sección [%2d] '%s': tamaño de entrada no coincide con Elf32_Word\n" -#: src/elflint.c:1961 +#: src/elflint.c:1965 #, c-format msgid "section [%2d] '%s': extended index table too small for symbol table\n" msgstr "" "Sección [%2d] '%s': tabla de índice extendida demasiado pequeña para tabla " "de símbolos\n" -#: src/elflint.c:1976 +#: src/elflint.c:1980 #, c-format msgid "" "section [%2d] '%s': extended section index in section [%2zu] '%s' refers to " @@ -2274,24 +2283,24 @@ msgstr "" "Sección [%2d] '%s': índice de sección extendida en sección [%2zu] '%s' se " "refiere a la misma tabla de símbolos\n" -#: src/elflint.c:1994 +#: src/elflint.c:1998 #, c-format msgid "symbol 0 should have zero extended section index\n" msgstr "símbolo 0 debe tener índice de sección extendida cero\n" -#: src/elflint.c:2006 +#: src/elflint.c:2010 #, c-format msgid "cannot get data for symbol %zu\n" msgstr "no puede obtener datos para símbolo %zu\n" -#: src/elflint.c:2011 +#: src/elflint.c:2015 #, c-format msgid "extended section index is % but symbol index is not XINDEX\n" msgstr "" "índice de sección extendida es % pero índice de símbolo no es " "XINDEX\n" -#: src/elflint.c:2028 src/elflint.c:2085 +#: src/elflint.c:2032 src/elflint.c:2089 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n" @@ -2299,42 +2308,42 @@ msgstr "" "Sección [%2d] '%s': sección de tabla de dispersión es demasiado pequeña (es " "%ld, se espera %ld)\n" -#: src/elflint.c:2042 src/elflint.c:2099 +#: src/elflint.c:2046 src/elflint.c:2103 #, c-format msgid "section [%2d] '%s': chain array too large\n" msgstr "Sección [%2d] '%s': índice de la cadena es demasiado grande\n" -#: src/elflint.c:2056 src/elflint.c:2113 +#: src/elflint.c:2060 src/elflint.c:2117 #, c-format msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n" msgstr "" "Sección [%2d] '%s': referencia de cubetas de dispersión %zu fuera de " "límites\n" -#: src/elflint.c:2066 +#: src/elflint.c:2070 #, c-format msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n" msgstr "" "Sección [%2d] '%s': referencia de cadena de dispersión %zu fuera de límites\n" -#: src/elflint.c:2123 +#: src/elflint.c:2127 #, c-format msgid "section [%2d] '%s': hash chain reference % out of bounds\n" msgstr "" "Sección [%2d] '%s': referencia de cadena de dispersión % fuera de " "límites\n" -#: src/elflint.c:2136 +#: src/elflint.c:2140 #, fuzzy, c-format msgid "section [%2d] '%s': not enough data\n" msgstr "Sección [%2d] '%s': no puede obtener datos: %s\n" -#: src/elflint.c:2148 +#: src/elflint.c:2152 #, fuzzy, c-format msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n" msgstr "Sección [%2d] '%s': tamaño de bitmask no es potencia de 2: %u\n" -#: src/elflint.c:2164 +#: src/elflint.c:2168 #, fuzzy, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected at " @@ -2343,14 +2352,14 @@ msgstr "" "Sección [%2d] '%s': sección de tabla de dispersión es demasiado pequeña (es " "%ld, se espera al menos least%ld)\n" -#: src/elflint.c:2173 +#: src/elflint.c:2177 #, c-format msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n" msgstr "" "Sección [%2d] '%s': segundo cambio de función de dispersión demasiado " "grande: %u\n" -#: src/elflint.c:2207 +#: src/elflint.c:2211 #, c-format msgid "" "section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n" @@ -2358,7 +2367,7 @@ msgstr "" "Sección [%2d] '%s': cadena de dispersión para cubetas %zu inferior a " "polarización de índice de símbolo\n" -#: src/elflint.c:2228 +#: src/elflint.c:2232 #, c-format msgid "" "section [%2d] '%s': symbol %u referenced in chain for bucket %zu is " @@ -2367,7 +2376,7 @@ msgstr "" "Sección [%2d] '%s': el símbolo %u al que se hace referencia en cadena para " "cubeta %zu es indefinido\n" -#: src/elflint.c:2241 +#: src/elflint.c:2245 #, c-format msgid "" "section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n" @@ -2375,7 +2384,7 @@ msgstr "" "Sección [%2d] '%s': valor de dispersión para símbolo %u en cadena para " "cubeta %zu está errado\n" -#: src/elflint.c:2250 +#: src/elflint.c:2254 #, fuzzy, c-format msgid "" "section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n" @@ -2383,13 +2392,13 @@ msgstr "" "Sección [%2d] '%s': valor de dispersión para símbolo %u en cadena para " "cubeta %zu está errado\n" -#: src/elflint.c:2280 +#: src/elflint.c:2284 #, c-format msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n" msgstr "" "Sección [%2d] '%s': cadena de dispersión para cubeta %zu fuera de limites\n" -#: src/elflint.c:2285 +#: src/elflint.c:2289 #, c-format msgid "" "section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n" @@ -2397,43 +2406,43 @@ msgstr "" "Sección [%2d] '%s': referencia de símbolo en cadena para cubeta %zu fuera de " "límites\n" -#: src/elflint.c:2291 +#: src/elflint.c:2295 #, c-format msgid "section [%2d] '%s': bitmask does not match names in the hash table\n" msgstr "" "Sección [%2d] '%s': bitmask no coincide con nombres en la tabla de " "dispersión\n" -#: src/elflint.c:2304 +#: src/elflint.c:2308 #, c-format msgid "section [%2d] '%s': relocatable files cannot have hash tables\n" msgstr "" "Sección [%2d] '%s': archivos reubicables no pueden tener tablas de " "dispersión\n" -#: src/elflint.c:2322 +#: src/elflint.c:2326 #, c-format msgid "section [%2d] '%s': hash table not for dynamic symbol table\n" msgstr "" "Sección [%2d] '%s': tabla de dispersión no para tabla de símbolos dinámicos\n" -#: src/elflint.c:2326 +#: src/elflint.c:2330 #, fuzzy, c-format msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n" msgstr "Sección [%2d] '%s': índice de sección de destino inválido\n" -#: src/elflint.c:2336 +#: src/elflint.c:2340 #, c-format msgid "section [%2d] '%s': hash table entry size incorrect\n" msgstr "" "Sección [%2d] '%s': tamaño incorrecto de entrada de tabla de dispersión\n" -#: src/elflint.c:2341 +#: src/elflint.c:2345 #, c-format msgid "section [%2d] '%s': not marked to be allocated\n" msgstr "Sección [%2d] '%s': no marcada para ser asignada\n" -#: src/elflint.c:2346 +#: src/elflint.c:2350 #, c-format msgid "" "section [%2d] '%s': hash table has not even room for initial administrative " @@ -2442,46 +2451,46 @@ msgstr "" "Sección [%2d] '%s': tabla de dispersión no tiene ni siquiera espacio para " "entradas administrativas iniciales\n" -#: src/elflint.c:2395 +#: src/elflint.c:2399 #, c-format msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n" msgstr "" "sh_link en secciones de dispersión [%2zu] '%s' y [%2zu] '%s' no son " "idénticas\n" -#: src/elflint.c:2419 src/elflint.c:2484 src/elflint.c:2519 +#: src/elflint.c:2423 src/elflint.c:2488 src/elflint.c:2523 #, fuzzy, c-format msgid "hash section [%2zu] '%s' does not contain enough data\n" msgstr "sección [%2zu] '%s' no debe ser ejecutable\n" -#: src/elflint.c:2440 +#: src/elflint.c:2444 #, fuzzy, c-format msgid "hash section [%2zu] '%s' has zero bit mask words\n" msgstr "Sección [%2d] '%s': grupo de sección sin palabra de banderas\n" -#: src/elflint.c:2451 src/elflint.c:2495 src/elflint.c:2532 +#: src/elflint.c:2455 src/elflint.c:2499 src/elflint.c:2536 #, fuzzy, c-format msgid "hash section [%2zu] '%s' uses too much data\n" msgstr "sección [%2zu] '%s' debe ser asignada\n" -#: src/elflint.c:2466 +#: src/elflint.c:2470 #, c-format msgid "" "hash section [%2zu] '%s' invalid symbol index % (max_nsyms: " "%, nentries: %\n" msgstr "" -#: src/elflint.c:2553 +#: src/elflint.c:2557 #, fuzzy, c-format msgid "hash section [%2zu] '%s' invalid sh_entsize\n" msgstr "Sección [%2zu]: nombre inválido\n" -#: src/elflint.c:2563 src/elflint.c:2567 +#: src/elflint.c:2567 src/elflint.c:2571 #, c-format msgid "section [%2zu] '%s': reference to symbol index 0\n" msgstr "Sección [%2zu] '%s': referencia al índice de símbolo 0\n" -#: src/elflint.c:2574 +#: src/elflint.c:2578 #, c-format msgid "" "symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash " @@ -2490,7 +2499,7 @@ msgstr "" "Símbolo %d nombrado en nueva tabla de dispersión en [%2zu] '%s' pero no en " "la tabla de dispersión anterior en [%2zu] '%s'\n" -#: src/elflint.c:2586 +#: src/elflint.c:2590 #, c-format msgid "" "symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash " @@ -2499,12 +2508,12 @@ msgstr "" "Símbolo %d nombrado en la tabla de dispersión anterior en [%2zu] '%s' pero " "no en la nueva tabla de dispersión en [%2zu] '%s'\n" -#: src/elflint.c:2602 +#: src/elflint.c:2606 #, c-format msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n" msgstr "Sección [%2d] '%s': nonzero sh_%s para sección NULL\n" -#: src/elflint.c:2622 +#: src/elflint.c:2626 #, c-format msgid "" "section [%2d] '%s': section groups only allowed in relocatable object files\n" @@ -2512,99 +2521,99 @@ msgstr "" "Sección [%2d] '%s': grupos de sección sólo permitidos en archivos de objeto " "reubicables\n" -#: src/elflint.c:2633 +#: src/elflint.c:2637 #, c-format msgid "section [%2d] '%s': cannot get symbol table: %s\n" msgstr "Sección [%2d] '%s': no puede obtener tabla de símbolos: %s\n" -#: src/elflint.c:2638 +#: src/elflint.c:2642 #, c-format msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n" msgstr "" "Sección [%2d] '%s': referencia de sección en sh_link no es una tabla de " "símbolos\n" -#: src/elflint.c:2644 +#: src/elflint.c:2648 #, c-format msgid "section [%2d] '%s': invalid symbol index in sh_info\n" msgstr "Sección [%2d] '%s': índice de símbolo inválido en sh_info\n" -#: src/elflint.c:2649 +#: src/elflint.c:2653 #, c-format msgid "section [%2d] '%s': sh_flags not zero\n" msgstr "Sección [%2d] '%s': sh_flags no cero\n" -#: src/elflint.c:2656 +#: src/elflint.c:2660 #, c-format msgid "section [%2d] '%s': cannot get symbol for signature\n" msgstr "Sección [%2d] '%s': no puede obtener símbolo para firma\n" -#: src/elflint.c:2660 +#: src/elflint.c:2664 #, fuzzy, c-format msgid "section [%2d] '%s': cannot get symbol name for signature\n" msgstr "Sección [%2d] '%s': no puede obtener símbolo para firma\n" -#: src/elflint.c:2665 +#: src/elflint.c:2669 #, c-format msgid "section [%2d] '%s': signature symbol cannot be empty string\n" msgstr "" "sección [%2d] '%s': el símbolo de firma no puede ser una cadena vacía\n" -#: src/elflint.c:2671 +#: src/elflint.c:2675 #, c-format msgid "section [%2d] '%s': sh_flags not set correctly\n" msgstr "Sección [%2d] '%s': sh_flags no establecida correctamente\n" -#: src/elflint.c:2677 +#: src/elflint.c:2681 #, c-format msgid "section [%2d] '%s': cannot get data: %s\n" msgstr "Sección [%2d] '%s': no puede obtener datos: %s\n" -#: src/elflint.c:2686 +#: src/elflint.c:2690 #, c-format msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n" msgstr "" "Sección [%2d] '%s': tamaño de sección no es múltiplo de tamaño de " "(Elf32_Word)\n" -#: src/elflint.c:2692 +#: src/elflint.c:2696 #, c-format msgid "section [%2d] '%s': section group without flags word\n" msgstr "Sección [%2d] '%s': grupo de sección sin palabra de banderas\n" -#: src/elflint.c:2700 +#: src/elflint.c:2704 #, c-format msgid "section [%2d] '%s': section group without member\n" msgstr "Sección [%2d] '%s': grupo de sección sin miembro\n" -#: src/elflint.c:2704 +#: src/elflint.c:2708 #, c-format msgid "section [%2d] '%s': section group with only one member\n" msgstr "Sección [%2d] '%s': grupo de sección con sólo un miembro\n" -#: src/elflint.c:2715 +#: src/elflint.c:2719 #, c-format msgid "section [%2d] '%s': unknown section group flags\n" msgstr "Sección [%2d] '%s': banderas de grupo de sección desconocido\n" -#: src/elflint.c:2727 +#: src/elflint.c:2731 #, fuzzy, c-format msgid "section [%2d] '%s': section index %zu out of range\n" msgstr "Sección [%2d] '%s': índice de sección %Zu fuera de rango\n" -#: src/elflint.c:2736 +#: src/elflint.c:2740 #, c-format msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n" msgstr "" "Sección [%2d] '%s': no se puede obtener encabezamiento de sección para " "elemento %zu: %s\n" -#: src/elflint.c:2743 +#: src/elflint.c:2747 #, c-format msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n" msgstr "Sección [%2d] '%s': grupo de sección contiene otro grupo [%2d] '%s'\n" -#: src/elflint.c:2749 +#: src/elflint.c:2753 #, fuzzy, c-format msgid "" "section [%2d] '%s': element %zu references section [%2d] '%s' without " @@ -2613,12 +2622,12 @@ msgstr "" "Sección [%2d] '%s': elemento %Zu hace referencia a sección [%2d] '%s' sin " "establecer bandera SHF_GROUP\n" -#: src/elflint.c:2756 +#: src/elflint.c:2760 #, c-format msgid "section [%2d] '%s' is contained in more than one section group\n" msgstr "Sección [%2d] '%s' está contenida en más de un grupo de sección\n" -#: src/elflint.c:2946 +#: src/elflint.c:2950 #, c-format msgid "" "section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no " @@ -2627,7 +2636,7 @@ msgstr "" "Sección [%2d] '%s' se refiere en sh_link a la sección [%2d] '%s' la cual no " "es una tabla de símbolos dinámicos\n" -#: src/elflint.c:2958 +#: src/elflint.c:2962 #, c-format msgid "" "section [%2d] '%s' has different number of entries than symbol table [%2d] " @@ -2636,29 +2645,29 @@ msgstr "" "Sección [%2d] '%s' tiene un número diferente de entradas a la de la tabla de " "símbolos [%2d] '%s'\n" -#: src/elflint.c:2974 +#: src/elflint.c:2978 #, c-format msgid "section [%2d] '%s': symbol %d: cannot read version data\n" msgstr "" "Sección [%2d] '%s': el símbolo %d: no se pueden leer datos de versión\n" -#: src/elflint.c:2990 +#: src/elflint.c:2994 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n" msgstr "" "Sección [%2d] '%s': el símbolo %d: el símbolo local con alcance mundial\n" -#: src/elflint.c:2998 +#: src/elflint.c:3002 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with version\n" msgstr "Sección [%2d] '%s': símbolo %d: símbolo local con versión\n" -#: src/elflint.c:3012 +#: src/elflint.c:3016 #, c-format msgid "section [%2d] '%s': symbol %d: invalid version index %d\n" msgstr "Sección [%2d] '%s': símbolo %d: índice de versión inválida %d\n" -#: src/elflint.c:3017 +#: src/elflint.c:3021 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for defined version\n" @@ -2666,7 +2675,7 @@ msgstr "" "Sección [%2d] '%s': símbolo %d: índice de versión %d es para versión " "definida\n" -#: src/elflint.c:3027 +#: src/elflint.c:3031 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for requested version\n" @@ -2674,46 +2683,46 @@ msgstr "" "Sección [%2d] '%s': símbolo %d: índice de versión %d es para la versión " "solicitada\n" -#: src/elflint.c:3080 +#: src/elflint.c:3084 #, c-format msgid "more than one version reference section present\n" msgstr "Más de una sección de referencia de versión presente\n" -#: src/elflint.c:3088 src/elflint.c:3235 +#: src/elflint.c:3092 src/elflint.c:3239 #, c-format msgid "section [%2d] '%s': sh_link does not link to string table\n" msgstr "Sección [%2d] '%s': sh_link no se enlaza a la tabla de cadenas\n" -#: src/elflint.c:3113 src/elflint.c:3289 +#: src/elflint.c:3117 src/elflint.c:3293 #, c-format msgid "section [%2d] '%s': entry %d has wrong version %d\n" msgstr "Sección [%2d] '%s': entrada %d tiene versión %d errada\n" -#: src/elflint.c:3120 src/elflint.c:3296 +#: src/elflint.c:3124 src/elflint.c:3300 #, c-format msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n" msgstr "" "Sección [%2d] '%s': entrada %d tiene compensación errada de datos " "auxiliares\n" -#: src/elflint.c:3130 +#: src/elflint.c:3134 #, c-format msgid "section [%2d] '%s': entry %d has invalid file reference\n" msgstr "Sección [%2d] '%s': entrada %d tiene referencia de archivo inválida\n" -#: src/elflint.c:3138 +#: src/elflint.c:3142 #, c-format msgid "section [%2d] '%s': entry %d references unknown dependency\n" msgstr "Sección [%2d] '%s': %d hace referencia a dependencia desconocida\n" -#: src/elflint.c:3150 +#: src/elflint.c:3154 #, c-format msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n" msgstr "" "sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene bandera " "desconocida\n" -#: src/elflint.c:3158 +#: src/elflint.c:3162 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has invalid name " @@ -2722,7 +2731,7 @@ msgstr "" "Sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene referencia de " "nombre inválida\n" -#: src/elflint.c:3167 +#: src/elflint.c:3171 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: " @@ -2731,7 +2740,7 @@ msgstr "" "Sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene valor de " "dispersión: %#x, esperado %#x\n" -#: src/elflint.c:3176 +#: src/elflint.c:3180 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version " @@ -2740,7 +2749,7 @@ msgstr "" "sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene nombre duplicado " "'%s'\n" -#: src/elflint.c:3187 +#: src/elflint.c:3191 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n" @@ -2748,14 +2757,14 @@ msgstr "" "sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene próximo campo " "errado\n" -#: src/elflint.c:3204 src/elflint.c:3380 +#: src/elflint.c:3208 src/elflint.c:3384 #, c-format msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n" msgstr "" "sección [%2d] '%s': entrada %d tiene compensación inválida para próxima " "entrada\n" -#: src/elflint.c:3212 src/elflint.c:3388 +#: src/elflint.c:3216 src/elflint.c:3392 #, fuzzy, c-format msgid "" "section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says " @@ -2764,46 +2773,46 @@ msgstr "" "sección [%2d] '%s': entrada %d tiene compensación inválida para próxima " "entrada\n" -#: src/elflint.c:3227 +#: src/elflint.c:3231 #, c-format msgid "more than one version definition section present\n" msgstr "más de una definición de versión presente de sección\n" -#: src/elflint.c:3274 +#: src/elflint.c:3278 #, c-format msgid "section [%2d] '%s': more than one BASE definition\n" msgstr "Sección [%2d] '%s': más de una definición de BASE\n" -#: src/elflint.c:3278 +#: src/elflint.c:3282 #, c-format msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n" msgstr "" "Sección [%2d] '%s': definición de BASE debe tener índice VER_NDX_GLOBAL\n" -#: src/elflint.c:3284 +#: src/elflint.c:3288 #, c-format msgid "section [%2d] '%s': entry %d has unknown flag\n" msgstr "Sección [%2d] '%s': entrada %d tiene bandera desconocida\n" -#: src/elflint.c:3311 +#: src/elflint.c:3315 #, c-format msgid "section [%2d] '%s': entry %d has invalid name reference\n" msgstr "Sección [%2d] '%s': entrada %d tiene referencia de nombre inválida\n" -#: src/elflint.c:3318 +#: src/elflint.c:3322 #, c-format msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n" msgstr "" "Sección [%2d] '%s': entrada %d tiene valor de dispersión errado: %#x, " "esperado %#x\n" -#: src/elflint.c:3326 +#: src/elflint.c:3330 #, c-format msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n" msgstr "" "Sección [%2d] '%s': entrada %d tiene nombre de versión duplicado '%s'\n" -#: src/elflint.c:3346 +#: src/elflint.c:3350 #, c-format msgid "" "section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n" @@ -2811,34 +2820,34 @@ msgstr "" "Sección [%2d] '%s': entrada %d tiene referencia de nombre inválida en datos " "auxiliares\n" -#: src/elflint.c:3363 +#: src/elflint.c:3367 #, c-format msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n" msgstr "" "Sección [%2d] '%s': entrada %d tiene próximo campo errado en datos " "auxiliares\n" -#: src/elflint.c:3396 +#: src/elflint.c:3400 #, c-format msgid "section [%2d] '%s': no BASE definition\n" msgstr "Sección [%2d] '%s': no hay definición de BASE\n" -#: src/elflint.c:3412 +#: src/elflint.c:3416 #, c-format msgid "section [%2d] '%s': unknown parent version '%s'\n" msgstr "Sección [%2d] '%s': desconocida versión principal '%s'\n" -#: src/elflint.c:3425 +#: src/elflint.c:3429 #, c-format msgid "section [%2d] '%s': empty object attributes section\n" msgstr "Sección [%2d] '%s': sección de atributos de objeto vacío\n" -#: src/elflint.c:3446 +#: src/elflint.c:3450 #, c-format msgid "section [%2d] '%s': unrecognized attribute format\n" msgstr "Sección[%2d] '%s': formato de atributo no reconocido\n" -#: src/elflint.c:3462 +#: src/elflint.c:3466 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute section\n" @@ -2846,21 +2855,21 @@ msgstr "" "Sección[%2d] '%s': compensación %zu: campo de longitud cero en sección de " "atributo\n" -#: src/elflint.c:3471 +#: src/elflint.c:3475 #, c-format msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n" msgstr "" "Sección[%2d] '%s': compensación %zu: longitud inválida en sección de " "atributo\n" -#: src/elflint.c:3483 +#: src/elflint.c:3487 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n" msgstr "" "Sección[%2d] '%s': compensación %zu: cadena de nombre de proveedor sin " "terminar\n" -#: src/elflint.c:3500 +#: src/elflint.c:3504 #, c-format msgid "" "section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n" @@ -2868,12 +2877,12 @@ msgstr "" "Sección [%2d] '%s': compensación %zu: sin fin ULEB128 en etiqueta de sub-" "sección de atributo\n" -#: src/elflint.c:3509 +#: src/elflint.c:3513 #, c-format msgid "section [%2d] '%s': offset %zu: truncated attribute section\n" msgstr "Sección [%2d] '%s': compensación %zu: sección de atributo truncado\n" -#: src/elflint.c:3518 +#: src/elflint.c:3522 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute subsection\n" @@ -2881,7 +2890,7 @@ msgstr "" "Sección [%2d] '%s': compensación %zu: campo de longitud cero length en sub-" "sección de atributo\n" -#: src/elflint.c:3533 +#: src/elflint.c:3537 #, c-format msgid "" "section [%2d] '%s': offset %zu: invalid length in attribute subsection\n" @@ -2890,7 +2899,7 @@ msgstr "" "atributo\n" #. Tag_File -#: src/elflint.c:3544 +#: src/elflint.c:3548 #, c-format msgid "" "section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n" @@ -2898,26 +2907,26 @@ msgstr "" "Sección[%2d] '%s': compensación %zu: sub-sección de atributo tiene etiqueta " "inesperada %u\n" -#: src/elflint.c:3562 +#: src/elflint.c:3566 #, c-format msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n" msgstr "" "Sección[%2d] '%s': compensación %zu: sin fin ULEB128 en etiqueta de " "atributo\n" -#: src/elflint.c:3573 +#: src/elflint.c:3577 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n" msgstr "" "Sección [%2d] '%s': compensación %zu: cadena sin terminar en atributo\n" -#: src/elflint.c:3586 +#: src/elflint.c:3590 #, c-format msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n" msgstr "" "Sección [%2d] '%s': compensación %zu: etiqueta de atributo no reconocida %u\n" -#: src/elflint.c:3590 +#: src/elflint.c:3594 #, c-format msgid "" "section [%2d] '%s': offset %zu: unrecognized %s attribute value %\n" @@ -2925,12 +2934,12 @@ msgstr "" "Sección [%2d] '%s': compensación %zu: no reconocido %s valor de atributo " "%\n" -#: src/elflint.c:3600 +#: src/elflint.c:3604 #, c-format msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n" msgstr "Sección [%2d] '%s': compensación %zu: proveedor '%s' desconocido\n" -#: src/elflint.c:3606 +#: src/elflint.c:3610 #, c-format msgid "" "section [%2d] '%s': offset %zu: extra bytes after last attribute section\n" @@ -2938,47 +2947,47 @@ msgstr "" "Sección [%2d] '%s': compensación %zu: extra bytes después de la última " "sección de atributo\n" -#: src/elflint.c:3695 +#: src/elflint.c:3699 #, c-format msgid "cannot get section header of zeroth section\n" msgstr "no puede obtener encabezamiento de sección de sección zeroth\n" -#: src/elflint.c:3699 +#: src/elflint.c:3703 #, c-format msgid "zeroth section has nonzero name\n" msgstr "Sección zeroth tiene nombre nonzero\n" -#: src/elflint.c:3701 +#: src/elflint.c:3705 #, c-format msgid "zeroth section has nonzero type\n" msgstr "Sección zeroth tiene tipo nonzero\n" -#: src/elflint.c:3703 +#: src/elflint.c:3707 #, c-format msgid "zeroth section has nonzero flags\n" msgstr "Sección zeroth tiene banderas nonzero\n" -#: src/elflint.c:3705 +#: src/elflint.c:3709 #, c-format msgid "zeroth section has nonzero address\n" msgstr "Sección zeroth tiene dirección nonzero\n" -#: src/elflint.c:3707 +#: src/elflint.c:3711 #, c-format msgid "zeroth section has nonzero offset\n" msgstr "Sección zeroth tiene compensación nonzero\n" -#: src/elflint.c:3709 +#: src/elflint.c:3713 #, c-format msgid "zeroth section has nonzero align value\n" msgstr "Sección zeroth tiene valor de alineación nonzero\n" -#: src/elflint.c:3711 +#: src/elflint.c:3715 #, c-format msgid "zeroth section has nonzero entry size value\n" msgstr "Sección zeroth tiene valor de tamaño de entrada nonzero\n" -#: src/elflint.c:3714 +#: src/elflint.c:3718 #, c-format msgid "" "zeroth section has nonzero size value while ELF header has nonzero shnum " @@ -2987,7 +2996,7 @@ msgstr "" "Sección zeroth tiene valor de tamaño nonzero mientras que el encabezamiento " "ELF tiene valor shnum nonzero\n" -#: src/elflint.c:3718 +#: src/elflint.c:3722 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " @@ -2996,7 +3005,7 @@ msgstr "" "Sección zeroth tiene valor de enlace nonzero mientras que el encabezamiento " "ELF no señala sobreflujo en shstrndx\n" -#: src/elflint.c:3722 +#: src/elflint.c:3726 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " @@ -3005,27 +3014,27 @@ msgstr "" "la sección zeroth tiene un valor de enlace distinto a cero mientras que el " "encabezamiento ELF no señala desbordamiento en phnum\n" -#: src/elflint.c:3740 +#: src/elflint.c:3744 #, c-format msgid "cannot get section header for section [%2zu] '%s': %s\n" msgstr "No se puede obtener encabezamiento para sección [%2zu] '%s': %s\n" -#: src/elflint.c:3749 +#: src/elflint.c:3753 #, c-format msgid "section [%2zu]: invalid name\n" msgstr "Sección [%2zu]: nombre inválido\n" -#: src/elflint.c:3776 +#: src/elflint.c:3780 #, c-format msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n" msgstr "Sección [%2d] '%s' tiene tipo errado: %s esperado, es %s\n" -#: src/elflint.c:3794 +#: src/elflint.c:3798 #, c-format msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n" msgstr "Sección [%2zu] '%s' tiene banderas erradas: %s esperado, es %s\n" -#: src/elflint.c:3812 +#: src/elflint.c:3816 #, c-format msgid "" "section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n" @@ -3033,12 +3042,12 @@ msgstr "" "Sección [%2zu] '%s' tiene banderas erradas: %s esperado y posiblemente %s, " "es %s\n" -#: src/elflint.c:3830 +#: src/elflint.c:3834 #, c-format msgid "section [%2zu] '%s' present in object file\n" msgstr "Sección [%2zu] '%s' presente en archivo objeto\n" -#: src/elflint.c:3836 src/elflint.c:3868 +#: src/elflint.c:3840 src/elflint.c:3872 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n" @@ -3046,7 +3055,7 @@ msgstr "" "Sección [%2zu] '%s' tiene bandera SHF_ALLOC establecida pero no es un " "segmento cargable\n" -#: src/elflint.c:3841 src/elflint.c:3873 +#: src/elflint.c:3845 src/elflint.c:3877 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable " @@ -3055,7 +3064,7 @@ msgstr "" "Sección [%2zu] '%s' no tiene bandera SHF_ALLOC establecida pero hay " "segmentos cargables\n" -#: src/elflint.c:3849 +#: src/elflint.c:3853 #, c-format msgid "" "section [%2zu] '%s' is extension section index table in non-object file\n" @@ -3063,22 +3072,22 @@ msgstr "" "Sección [%2zu] '%s' es tabla de índice de sección de extensión en archivo no-" "objeto\n" -#: src/elflint.c:3892 +#: src/elflint.c:3896 #, c-format msgid "section [%2zu] '%s': size not multiple of entry size\n" msgstr "Sección [%2zu] '%s': tamaño no es múltiplo de tamaño de entrada\n" -#: src/elflint.c:3897 +#: src/elflint.c:3901 #, c-format msgid "cannot get section header\n" msgstr "no se puede obtener encabezamiento de sección\n" -#: src/elflint.c:3907 +#: src/elflint.c:3911 #, c-format msgid "section [%2zu] '%s' has unsupported type %d\n" msgstr "sección [%2zu] '%s' tiene tipo %d incompatible \n" -#: src/elflint.c:3922 +#: src/elflint.c:3926 #, c-format msgid "" "section [%2zu] '%s' contains invalid processor-specific flag(s) %#\n" @@ -3086,76 +3095,76 @@ msgstr "" "Sección [%2zu] '%s' contiene bandera(s) de procesador-específico inválidas " "%#\n" -#: src/elflint.c:3929 +#: src/elflint.c:3933 #, c-format msgid "section [%2zu] '%s' contains unknown flag(s) %#\n" msgstr "Sección [%2zu] '%s' contiene bandera(s) desconocidas %#\n" -#: src/elflint.c:3937 +#: src/elflint.c:3941 #, c-format msgid "section [%2zu] '%s': thread-local data sections address not zero\n" msgstr "" "Sección [%2zu] '%s': dirección de secciones de datos de hilo-local no cero\n" -#: src/elflint.c:3947 +#: src/elflint.c:3951 #, fuzzy, c-format msgid "section [%2zu] '%s': allocated section cannot be compressed\n" msgstr "" "Sección [%2zu] '%s': dirección de secciones de datos de hilo-local no cero\n" -#: src/elflint.c:3952 +#: src/elflint.c:3956 #, fuzzy, c-format msgid "section [%2zu] '%s': nobits section cannot be compressed\n" msgstr "Sección [%2d] '%s': no hay sección de dispersión presente\n" -#: src/elflint.c:3958 +#: src/elflint.c:3962 #, fuzzy, c-format msgid "" "section [%2zu] '%s': compressed section with no compression header: %s\n" msgstr "Sección [%2d] '%s': grupo de sección con sólo un miembro\n" -#: src/elflint.c:3964 +#: src/elflint.c:3968 #, c-format msgid "section [%2zu] '%s': invalid section reference in link value\n" msgstr "" "Sección [%2zu] '%s': referencia de sección inválida en valor de enlace\n" -#: src/elflint.c:3969 +#: src/elflint.c:3973 #, c-format msgid "section [%2zu] '%s': invalid section reference in info value\n" msgstr "" "Sección [%2zu] '%s': referencia de sección inválida en valor de información\n" -#: src/elflint.c:3976 +#: src/elflint.c:3980 #, c-format msgid "section [%2zu] '%s': strings flag set without merge flag\n" msgstr "" "Sección [%2zu] '%s': bandera de cadenas establecida sin bandera de fusión\n" -#: src/elflint.c:3981 +#: src/elflint.c:3985 #, c-format msgid "section [%2zu] '%s': merge flag set but entry size is zero\n" msgstr "" "Sección [%2zu] '%s': bandera de fusión establecida pero tamaño de entrada es " "cero\n" -#: src/elflint.c:4000 +#: src/elflint.c:4004 #, c-format msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n" msgstr "" "Sección [%2zu] '%s' tiene un tipo %d inesperado para una sección ejecutable\n" -#: src/elflint.c:4009 +#: src/elflint.c:4013 #, fuzzy, c-format msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n" msgstr "sección [%2zu] '%s' no debe tener permiso de escritura\n" -#: src/elflint.c:4016 +#: src/elflint.c:4020 #, c-format msgid "section [%2zu] '%s' is both executable and writable\n" msgstr "Sección [%2zu] '%s' es tanto de ejecución como de escritura\n" -#: src/elflint.c:4047 +#: src/elflint.c:4051 #, c-format msgid "" "section [%2zu] '%s' not fully contained in segment of program header entry " @@ -3164,7 +3173,7 @@ msgstr "" "Sección [%2zu] '%s' no contenida totalmente en segmento de entrada de " "encabezamiento de programa %d\n" -#: src/elflint.c:4057 +#: src/elflint.c:4061 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " @@ -3173,7 +3182,7 @@ msgstr "" "Sección [%2zu] '%s' no tiene tipo NOBITS pero es leída desde el archivo en " "segmento de entrada de encabezamiento de programa %d\n" -#: src/elflint.c:4083 +#: src/elflint.c:4087 #, fuzzy, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " @@ -3182,7 +3191,7 @@ msgstr "" "Sección [%2zu] '%s' no tiene tipo NOBITS pero es leída desde el archivo en " "segmento de entrada de encabezamiento de programa %d\n" -#: src/elflint.c:4094 +#: src/elflint.c:4098 #, c-format msgid "" "section [%2zu] '%s' has not type NOBITS but is not read from the file in " @@ -3191,18 +3200,18 @@ msgstr "" "Sección [%2zu] '%s' no tiene tipo NOBITS pero no es leída desde el fichero " "en segmento de entrada de encabezamiento de programa %d\n" -#: src/elflint.c:4105 +#: src/elflint.c:4109 #, c-format msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n" msgstr "Sección [%2zu] '%s' es ejecutable en segmento no ejecutable %d\n" -#: src/elflint.c:4115 +#: src/elflint.c:4119 #, c-format msgid "section [%2zu] '%s' is writable in unwritable segment %d\n" msgstr "" "Sección [%2zu] '%s' es de escritura en segmento que no es de escritura %d\n" -#: src/elflint.c:4125 +#: src/elflint.c:4129 #, c-format msgid "" "section [%2zu] '%s': alloc flag set but section not in any loaded segment\n" @@ -3210,7 +3219,7 @@ msgstr "" "Sección [%2zu] '%s': asignación de bandera establecida pero sección no en " "ningún segmento cargado\n" -#: src/elflint.c:4131 +#: src/elflint.c:4135 #, c-format msgid "" "section [%2zu] '%s': ELF header says this is the section header string table " @@ -3219,7 +3228,7 @@ msgstr "" "Sección [%2zu] '%s': encabezamiento ELF dice esta es la tabla de cadena de " "encabezamiento de sección, pero el tipo no es SHT_TYPE\n" -#: src/elflint.c:4139 +#: src/elflint.c:4143 #, c-format msgid "" "section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n" @@ -3227,32 +3236,32 @@ msgstr "" "sección [%2zu] '%s': ficheros reubicables no pueden tener tablas de símbolos " "dinámicos\n" -#: src/elflint.c:4190 +#: src/elflint.c:4194 #, c-format msgid "more than one version symbol table present\n" msgstr "Más de una tabla de símbolos presente\n" -#: src/elflint.c:4213 +#: src/elflint.c:4217 #, c-format msgid "INTERP program header entry but no .interp section\n" msgstr "" "Entrada de encabezamiento de programa INTERP pero no la sección .interp\n" -#: src/elflint.c:4224 +#: src/elflint.c:4228 #, c-format msgid "" "loadable segment [%u] is executable but contains no executable sections\n" msgstr "" "segmento cargable [%u] es ejecutable pero no contiene secciones ejecutables\n" -#: src/elflint.c:4230 +#: src/elflint.c:4234 #, c-format msgid "loadable segment [%u] is writable but contains no writable sections\n" msgstr "" "segmento cargable [%u] es de escritura pero contiene secciones protegidas " "contra escritura\n" -#: src/elflint.c:4241 +#: src/elflint.c:4245 #, c-format msgid "" "no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section " @@ -3261,26 +3270,26 @@ msgstr "" "Sección no .gnu.versym presente, pero la sección .gnu.versym_d o la sección ." "gnu.versym_r existen\n" -#: src/elflint.c:4254 +#: src/elflint.c:4258 #, c-format msgid "duplicate version index %d\n" msgstr "Duplicar índice de versión %d\n" -#: src/elflint.c:4268 +#: src/elflint.c:4272 #, c-format msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n" msgstr "" "Sección .gnu.versym presente sin las secciones .gnu.versym_d o .gnu." "versym_r\n" -#: src/elflint.c:4317 +#: src/elflint.c:4321 #, c-format msgid "phdr[%d]: unknown core file note type % at offset %\n" msgstr "" "phdr[%d]: tipo de nota de fichero core desconocido % en compensación " "%\n" -#: src/elflint.c:4321 +#: src/elflint.c:4325 #, fuzzy, c-format msgid "" "section [%2d] '%s': unknown core file note type % at offset %zu\n" @@ -3288,7 +3297,7 @@ msgstr "" "Sección [%2d] '%s': tipo de nota de fichero core desconocido % en " "compensación %Zu\n" -#: src/elflint.c:4370 +#: src/elflint.c:4374 #, fuzzy, c-format msgid "" "phdr[%d]: unknown object file note type % with owner name '%s' at " @@ -3297,7 +3306,7 @@ msgstr "" "phdr[%d]: tipo de nota de fichero objeto desconocido % en " "compensación %Zu\n" -#: src/elflint.c:4375 +#: src/elflint.c:4379 #, fuzzy, c-format msgid "" "section [%2d] '%s': unknown object file note type % with owner name " @@ -3306,40 +3315,40 @@ msgstr "" "Sección [%2d] '%s': tipo de nota de fichero objeto desconocido % en " "compensación %Zu\n" -#: src/elflint.c:4394 +#: src/elflint.c:4398 #, c-format msgid "phdr[%d]: no note entries defined for the type of file\n" msgstr "phdr[%d]: no hay entradas de nota definidas para el tipo de archivo\n" -#: src/elflint.c:4414 +#: src/elflint.c:4418 #, c-format msgid "phdr[%d]: cannot get content of note section: %s\n" msgstr "phdr[%d]: no puede obtener contenido de sección de nota: %s\n" -#: src/elflint.c:4417 +#: src/elflint.c:4421 #, c-format msgid "phdr[%d]: extra % bytes after last note\n" msgstr "phdr[%d]: extra % bytes después de la última nota\n" -#: src/elflint.c:4438 +#: src/elflint.c:4442 #, c-format msgid "section [%2d] '%s': no note entries defined for the type of file\n" msgstr "" "Sección [%2d] '%s': no hay entradas de nota definidas para el tipo de " "archivo\n" -#: src/elflint.c:4445 +#: src/elflint.c:4449 #, c-format msgid "section [%2d] '%s': cannot get content of note section\n" msgstr "" "Sección[%2d] '%s': no se puede obtener el contenido de sección de nota\n" -#: src/elflint.c:4448 +#: src/elflint.c:4452 #, c-format msgid "section [%2d] '%s': extra % bytes after last note\n" msgstr "Sección[%2d] '%s': extra % bytes después de la última nota\n" -#: src/elflint.c:4466 +#: src/elflint.c:4470 #, c-format msgid "" "only executables, shared objects, and core files can have program headers\n" @@ -3347,145 +3356,145 @@ msgstr "" "Sólo ejecutables, objetos compartidos y ficheros core pueden tener " "encabezamientos de programas\n" -#: src/elflint.c:4481 +#: src/elflint.c:4485 #, c-format msgid "cannot get program header entry %d: %s\n" msgstr "no se puede obtener entrada de encabezamiento %d: %s\n" -#: src/elflint.c:4490 +#: src/elflint.c:4499 #, c-format msgid "program header entry %d: unknown program header entry type %#\n" msgstr "" "entrada de encabezamiento de programa %d: tipo %# de entrada de " "encabezamiento de programa desconocido\n" -#: src/elflint.c:4501 +#: src/elflint.c:4510 #, c-format msgid "more than one INTERP entry in program header\n" msgstr "Más de una entrada INTERP en encabezamiento de programa\n" -#: src/elflint.c:4509 +#: src/elflint.c:4518 #, c-format msgid "more than one TLS entry in program header\n" msgstr "más de una entrada TLS en encabezamiento de programa\n" -#: src/elflint.c:4516 +#: src/elflint.c:4525 #, c-format msgid "static executable cannot have dynamic sections\n" msgstr "ejecutable estático no puede tener secciones dinámicas\n" -#: src/elflint.c:4530 +#: src/elflint.c:4539 #, c-format msgid "dynamic section reference in program header has wrong offset\n" msgstr "" "Referencia de sección dinámica en encabezamiento de programa tiene " "compensación errada\n" -#: src/elflint.c:4533 +#: src/elflint.c:4542 #, c-format msgid "dynamic section size mismatch in program and section header\n" msgstr "" "No coinciden tamaño de sección dinámica en programa y encabezamiento de " "sección\n" -#: src/elflint.c:4543 +#: src/elflint.c:4552 #, c-format msgid "more than one GNU_RELRO entry in program header\n" msgstr "Más de una entrada GNU_RELRO en encabezamiento de programa\n" -#: src/elflint.c:4564 +#: src/elflint.c:4573 #, c-format msgid "loadable segment GNU_RELRO applies to is not writable\n" msgstr "Segmento cargable GNU_RELRO que se aplica no es de escritura\n" -#: src/elflint.c:4575 +#: src/elflint.c:4584 #, c-format msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n" msgstr "" "Banderas de segmento cargable [%u] no coinciden con banderas GNU_RELRO [%u]\n" -#: src/elflint.c:4582 +#: src/elflint.c:4591 #, c-format msgid "" "GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n" msgstr "" -#: src/elflint.c:4591 src/elflint.c:4614 +#: src/elflint.c:4600 src/elflint.c:4623 #, c-format msgid "%s segment not contained in a loaded segment\n" msgstr "Segmento %s no contenido en un segmento cargable\n" -#: src/elflint.c:4620 +#: src/elflint.c:4629 #, c-format msgid "program header offset in ELF header and PHDR entry do not match" msgstr "" "Compensación de encabezamiento de programa en encabezamiento ELF y entrada " "PHDR no coinciden" -#: src/elflint.c:4647 +#: src/elflint.c:4656 #, c-format msgid "call frame search table reference in program header has wrong offset\n" msgstr "" "Referencia de tabla de búsqueda de marco de llamada en encabezamiento de " "programa tiene una compensación errada\n" -#: src/elflint.c:4650 +#: src/elflint.c:4659 #, c-format msgid "call frame search table size mismatch in program and section header\n" msgstr "" "Tamaño de tabla de búsqueda de marco de llamada no coincide con programa y " "encabezamiento de sección\n" -#: src/elflint.c:4663 +#: src/elflint.c:4672 #, c-format msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n" msgstr "PT_GNU_EH_FRAME presente pero no la sección.eh_frame_hdr\n" -#: src/elflint.c:4671 +#: src/elflint.c:4680 #, c-format msgid "call frame search table must be allocated\n" msgstr "tabla de búsqueda de marco de llamada debe ser asignada\n" -#: src/elflint.c:4674 +#: src/elflint.c:4683 #, c-format msgid "section [%2zu] '%s' must be allocated\n" msgstr "sección [%2zu] '%s' debe ser asignada\n" -#: src/elflint.c:4678 +#: src/elflint.c:4687 #, c-format msgid "call frame search table must not be writable\n" msgstr "" "tabla de búsqueda de marco de llamada no debe tener permiso de escritura\n" -#: src/elflint.c:4681 +#: src/elflint.c:4690 #, c-format msgid "section [%2zu] '%s' must not be writable\n" msgstr "sección [%2zu] '%s' no debe tener permiso de escritura\n" -#: src/elflint.c:4686 +#: src/elflint.c:4695 #, c-format msgid "call frame search table must not be executable\n" msgstr "tabla de búsqueda de marco de llamada no debe ser ejecutable\n" -#: src/elflint.c:4689 +#: src/elflint.c:4698 #, c-format msgid "section [%2zu] '%s' must not be executable\n" msgstr "sección [%2zu] '%s' no debe ser ejecutable\n" -#: src/elflint.c:4700 +#: src/elflint.c:4709 #, c-format msgid "program header entry %d: file size greater than memory size\n" msgstr "" "entrada de encabezamiento de programa %d: tamaño de fichero mayor que el " "tamaño de memoria\n" -#: src/elflint.c:4707 +#: src/elflint.c:4716 #, c-format msgid "program header entry %d: alignment not a power of 2\n" msgstr "" "entrada de encabezamiento de programa %d: alineamiento no es potencia de 2\n" -#: src/elflint.c:4710 +#: src/elflint.c:4719 #, c-format msgid "" "program header entry %d: file offset and virtual address not module of " @@ -3494,7 +3503,7 @@ msgstr "" "entrada de encabezamiento de programa %d: compensación de fichero y " "dirección virtual no módulo de alineación\n" -#: src/elflint.c:4723 +#: src/elflint.c:4732 #, c-format msgid "" "executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME " @@ -3503,12 +3512,12 @@ msgstr "" "ejecutable/DSO con sección .eh_frame_hdr no tiene una entrada de " "encabezamiento de programa PT_GNU_EH_FRAME" -#: src/elflint.c:4757 +#: src/elflint.c:4766 #, c-format msgid "cannot read ELF header: %s\n" msgstr "No se puede leer encabezamiento ELF: %s\n" -#: src/elflint.c:4783 +#: src/elflint.c:4792 #, c-format msgid "text relocation flag set but not needed\n" msgstr "Bandera de reubicación de texto establecida pero no necesaria\n" diff --git a/libdrgn/elfutils/po/ja.po b/libdrgn/elfutils/po/ja.po index cd53f220c..97a529bdd 100644 --- a/libdrgn/elfutils/po/ja.po +++ b/libdrgn/elfutils/po/ja.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: ja\n" "Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n" -"POT-Creation-Date: 2019-11-26 09:48+0100\n" +"POT-Creation-Date: 2020-03-30 12:56+0200\n" "PO-Revision-Date: 2009-09-20 15:32+0900\n" "Last-Translator: Hyu_gabaru Ryu_ichi \n" "Language-Team: Japanese \n" @@ -530,7 +530,7 @@ msgstr "バックエンドがありません" #: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:77 #: libebl/eblobjnotetypename.c:109 libebl/eblobjnotetypename.c:130 #: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83 -#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:79 +#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:85 msgid "" msgstr "<不明>" @@ -1677,14 +1677,14 @@ msgstr "" "セクション [%2d] '%s': セクショングループ [%2zu] '%s' がグループメンバーを継" "続していません\n" -#: src/elflint.c:610 src/elflint.c:1494 src/elflint.c:1545 src/elflint.c:1651 -#: src/elflint.c:1987 src/elflint.c:2313 src/elflint.c:2932 src/elflint.c:3095 -#: src/elflint.c:3243 src/elflint.c:3433 src/elflint.c:4431 +#: src/elflint.c:610 src/elflint.c:1498 src/elflint.c:1549 src/elflint.c:1655 +#: src/elflint.c:1991 src/elflint.c:2317 src/elflint.c:2936 src/elflint.c:3099 +#: src/elflint.c:3247 src/elflint.c:3437 src/elflint.c:4435 #, c-format msgid "section [%2d] '%s': cannot get section data\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:623 src/elflint.c:1658 +#: src/elflint.c:623 src/elflint.c:1662 #, c-format msgid "" "section [%2d] '%s': referenced as string table for section [%2d] '%s' but " @@ -1707,33 +1707,40 @@ msgstr "" msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n" msgstr "セクション [%2u] '%s': 項目サイズが ElfXX_Sym と一致しません\n" -#: src/elflint.c:667 +#: src/elflint.c:662 +#, c-format +msgid "" +"section [%2u] '%s': number of local entries in 'st_info' larger than table " +"size\n" +msgstr "" + +#: src/elflint.c:671 #, c-format msgid "section [%2d] '%s': cannot get symbol %d: %s\n" msgstr "セクション [%2d] '%s': シンボル %d を得られません: %s\n" -#: src/elflint.c:672 src/elflint.c:675 src/elflint.c:678 src/elflint.c:681 -#: src/elflint.c:684 src/elflint.c:687 +#: src/elflint.c:676 src/elflint.c:679 src/elflint.c:682 src/elflint.c:685 +#: src/elflint.c:688 src/elflint.c:691 #, c-format msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n" msgstr "セクション [%2d] '%s': 0番目の項目にある '%s' ゼロではありません\n" -#: src/elflint.c:690 +#: src/elflint.c:694 #, c-format msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n" msgstr "セクション [%2d] '%s': 0番目の項目用の XINDEX がゼロではありません\n" -#: src/elflint.c:700 +#: src/elflint.c:704 #, c-format msgid "section [%2d] '%s': cannot get symbol %zu: %s\n" msgstr "セクション [%2d] '%s': シンボル %zu を得られません: %s\n" -#: src/elflint.c:709 +#: src/elflint.c:713 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid name value\n" msgstr "セクション [%2d] '%s': シンボル %zu: 不当な名前の値\n" -#: src/elflint.c:724 +#: src/elflint.c:728 #, c-format msgid "" "section [%2d] '%s': symbol %zu: too large section index but no extended " @@ -1742,7 +1749,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: 大きすぎるセクションインデックスだが、拡" "張セクションインデックスセクションがありません\n" -#: src/elflint.c:730 +#: src/elflint.c:734 #, c-format msgid "" "section [%2d] '%s': symbol %zu: XINDEX used for index which would fit in " @@ -1752,29 +1759,29 @@ msgstr "" "クス用に使われる XINDEX\n" #. || sym->st_shndx > SHN_HIRESERVE always false -#: src/elflint.c:742 +#: src/elflint.c:746 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid section index\n" msgstr "セクション [%2d] '%s': シンボル %zu: 不当なセクションインデックス\n" -#: src/elflint.c:750 +#: src/elflint.c:754 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown type\n" msgstr "セクション [%2d] '%s': シンボル %zu: 不明なタイプ\n" -#: src/elflint.c:756 +#: src/elflint.c:760 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown symbol binding\n" msgstr "セクション [%2d] '%s': シンボル %zu: 不明なシンボルバインディング\n" -#: src/elflint.c:761 +#: src/elflint.c:765 #, c-format msgid "section [%2d] '%s': symbol %zu: unique symbol not of object type\n" msgstr "" "セクション [%2d] '%s': シンボル %zu: オブジェクトタイプと異なる固有のシンボ" "ル\n" -#: src/elflint.c:769 +#: src/elflint.c:773 #, c-format msgid "" "section [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n" @@ -1782,14 +1789,14 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: COMMON はリロケータブルファイル内のみで" "許されます\n" -#: src/elflint.c:773 +#: src/elflint.c:777 #, c-format msgid "section [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n" msgstr "" "セクション [%2d] '%s': シンボル %zu: ローカルな COMMON シンボルは意味がありま" "せん\n" -#: src/elflint.c:777 +#: src/elflint.c:781 #, c-format msgid "" "section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n" @@ -1797,12 +1804,12 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: COMMON セクションの機能は意味がありませ" "ん\n" -#: src/elflint.c:828 +#: src/elflint.c:832 #, c-format msgid "section [%2d] '%s': symbol %zu: st_value out of bounds\n" msgstr "セクション [%2d] '%s': シンボル %zu: st_value 境界外\n" -#: src/elflint.c:834 src/elflint.c:859 src/elflint.c:908 +#: src/elflint.c:838 src/elflint.c:863 src/elflint.c:912 #, c-format msgid "" "section [%2d] '%s': symbol %zu does not fit completely in referenced section " @@ -1811,7 +1818,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu は参照されるセクション [%2d] '%s' とは完" "全に一致しません\n" -#: src/elflint.c:843 +#: src/elflint.c:847 #, c-format msgid "" "section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have " @@ -1820,7 +1827,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: 参照されるセクション [%2d] '%s' は " "SHF_TLS フラグが設定されていません\n" -#: src/elflint.c:853 src/elflint.c:901 +#: src/elflint.c:857 src/elflint.c:905 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section " @@ -1829,7 +1836,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: st_value 参照されるセクション [%2d] " "'%s' の境界外\n" -#: src/elflint.c:880 +#: src/elflint.c:884 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n" @@ -1837,7 +1844,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: TLS プログラムヘッダー項目がない TLS シ" "ンボル\n" -#: src/elflint.c:886 +#: src/elflint.c:890 #, fuzzy, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program " @@ -1846,7 +1853,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: TLS プログラムヘッダー項目がない TLS シ" "ンボル\n" -#: src/elflint.c:894 +#: src/elflint.c:898 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] " @@ -1855,7 +1862,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: 参照されるセクション [%2d] '%s' の" "st_value 不足\n" -#: src/elflint.c:921 +#: src/elflint.c:925 #, c-format msgid "" "section [%2d] '%s': symbol %zu: local symbol outside range described in " @@ -1864,7 +1871,7 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: sh_info に記述された範囲外のローカルシン" "ボル\n" -#: src/elflint.c:928 +#: src/elflint.c:932 #, c-format msgid "" "section [%2d] '%s': symbol %zu: non-local symbol outside range described in " @@ -1873,12 +1880,12 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: sh_info に記述された範囲外の非ローカルシ" "ンボル\n" -#: src/elflint.c:935 +#: src/elflint.c:939 #, c-format msgid "section [%2d] '%s': symbol %zu: non-local section symbol\n" msgstr "セクション [%2d] '%s': シンボル %zu: 非ローカルセクションシンボル\n" -#: src/elflint.c:985 +#: src/elflint.c:989 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section " @@ -1887,7 +1894,7 @@ msgstr "" "セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルが間違ったセクション " "[%2d] を参照しています\n" -#: src/elflint.c:992 +#: src/elflint.c:996 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] " @@ -1899,7 +1906,7 @@ msgstr "" #. This test is more strict than the psABIs which #. usually allow the symbol to be in the middle of #. the .got section, allowing negative offsets. -#: src/elflint.c:1008 +#: src/elflint.c:1012 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %# does not " @@ -1908,7 +1915,7 @@ msgstr "" "セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボル値 %# は %s のセ" "クションアドレス %# と一致しません\n" -#: src/elflint.c:1015 +#: src/elflint.c:1019 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size % does not " @@ -1917,7 +1924,7 @@ msgstr "" "セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルサイズ % は %s " "のセクションサイズ % と一致しません\n" -#: src/elflint.c:1023 +#: src/elflint.c:1027 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got " @@ -1926,7 +1933,7 @@ msgstr "" "セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルはありますが、.got セク" "ションがありません\n" -#: src/elflint.c:1039 +#: src/elflint.c:1043 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC_ symbol value %# does not match dynamic " @@ -1935,7 +1942,7 @@ msgstr "" "セクション [%2d] '%s': _DYNAMIC_ シンボル値 %# は動的セグメントアドレ" "ス %# と一致しません\n" -#: src/elflint.c:1046 +#: src/elflint.c:1050 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC symbol size % does not match dynamic " @@ -1944,7 +1951,7 @@ msgstr "" "セクション [%2d] '%s': _DYNAMIC シンボルサイズ % は動的セグメントサイ" "ズ % と一致しません\n" -#: src/elflint.c:1059 +#: src/elflint.c:1063 #, c-format msgid "" "section [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-" @@ -1953,29 +1960,29 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: 省略以外の可視性を持った動的シンボルテー" "ブル中のシンボル\n" -#: src/elflint.c:1063 +#: src/elflint.c:1067 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown bit set in st_other\n" msgstr "" "セクション [%2d] '%s': シンボル %zu: st_other 中に設定された不明なビット\n" -#: src/elflint.c:1101 +#: src/elflint.c:1105 #, fuzzy, c-format msgid "section [%2d] '%s': cannot get section data.\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:1117 +#: src/elflint.c:1121 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n" msgstr "セクション [%2d] '%s': この RELA セクション用に使われる DT_RELCOUNT\n" -#: src/elflint.c:1128 src/elflint.c:1181 +#: src/elflint.c:1132 src/elflint.c:1185 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n" msgstr "" "セクション [%2d] '%s': このセクション用には高すぎる DT_RELCOUNT 値 %d\n" -#: src/elflint.c:1153 src/elflint.c:1206 +#: src/elflint.c:1157 src/elflint.c:1210 #, c-format msgid "" "section [%2d] '%s': relative relocations after index %d as specified by " @@ -1984,7 +1991,7 @@ msgstr "" "セクション [%2d] '%s': UT_RELOCOUNT で指定されたインデックス %d 後の相対リロ" "ケーション\n" -#: src/elflint.c:1159 src/elflint.c:1212 +#: src/elflint.c:1163 src/elflint.c:1216 #, c-format msgid "" "section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT " @@ -1993,52 +2000,52 @@ msgstr "" "セクション [%2d] '%s': インデックス %zu での非相対リロケーション; %d 相対リ" "ロケーションで指定された DT_RELCOUNT\n" -#: src/elflint.c:1171 +#: src/elflint.c:1175 #, c-format msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n" msgstr "セクション [%2d] '%s': この REL セクション用に使われる DT_RELACOUNT\n" -#: src/elflint.c:1254 +#: src/elflint.c:1258 #, c-format msgid "section [%2d] '%s': invalid destination section index\n" msgstr "セクション [%2d] '%s': 不当な宛先セクションインデックス\n" -#: src/elflint.c:1266 +#: src/elflint.c:1270 #, c-format msgid "section [%2d] '%s': invalid destination section type\n" msgstr "セクション [%2d] '%s': 不当な宛先セクションタイプ\n" -#: src/elflint.c:1274 +#: src/elflint.c:1278 #, c-format msgid "section [%2d] '%s': sh_info should be zero\n" msgstr "セクション [%2d] '%s': sh_info はゼロでなければなりません\n" -#: src/elflint.c:1282 +#: src/elflint.c:1286 #, fuzzy, c-format msgid "" "section [%2d] '%s': no relocations for merge-able string sections possible\n" msgstr "" "セクション [%2d] '%s': マージできるセクションのリロケーションは不可能です\n" -#: src/elflint.c:1290 +#: src/elflint.c:1294 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n" msgstr "" "セクション [%2d] '%s': セクション項目サイズが ElfXX_Rela と一致しません\n" -#: src/elflint.c:1350 +#: src/elflint.c:1354 #, c-format msgid "text relocation flag set but there is no read-only segment\n" msgstr "" "テキストリロケーションフラグが設定されていますが、読込み専用セグメントがあり" "ません\n" -#: src/elflint.c:1377 +#: src/elflint.c:1381 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid type\n" msgstr "セクション [%2d] '%s': リロケーション %zu: 不当なタイプ\n" -#: src/elflint.c:1385 +#: src/elflint.c:1389 #, c-format msgid "" "section [%2d] '%s': relocation %zu: relocation type invalid for the file " @@ -2047,13 +2054,13 @@ msgstr "" "セクション [%2d] '%s': リロケーション %zu: このファイル用のリロケーションタイ" "プは不当です\n" -#: src/elflint.c:1393 +#: src/elflint.c:1397 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n" msgstr "" "セクション [%2d] '%s': リロケーション %zu: 不当なシンボルインデックス\n" -#: src/elflint.c:1411 +#: src/elflint.c:1415 #, c-format msgid "" "section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can " @@ -2062,12 +2069,12 @@ msgstr "" "セクション [%2d] '%s': リロケーション %zu: シンボル '_GLOBAL_OFFSET_TABLE_' " "のみが %s と一緒に使用できます\n" -#: src/elflint.c:1428 +#: src/elflint.c:1432 #, c-format msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n" msgstr "セクション [%2d] '%s': リロケーション %zu: オフセット境界外\n" -#: src/elflint.c:1443 +#: src/elflint.c:1447 #, c-format msgid "" "section [%2d] '%s': relocation %zu: copy relocation against symbol of type " @@ -2076,7 +2083,7 @@ msgstr "" "セクション [%2d] '%s': リロケーション %zu: タイプ %s のシンボルに対するコピー" "リロケーション\n" -#: src/elflint.c:1464 +#: src/elflint.c:1468 #, c-format msgid "" "section [%2d] '%s': relocation %zu: read-only section modified but text " @@ -2085,24 +2092,24 @@ msgstr "" "セクション [%2d] '%s': リロケーション %zu: 読込み専用セクションが変更されまし" "たが、テキストリロケーションフラグが設定されていません\n" -#: src/elflint.c:1479 +#: src/elflint.c:1483 #, c-format msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n" msgstr "" "セクション [%2d] '%s': リロケーションがロードされたデータとロードされなかった" "データに対してです\n" -#: src/elflint.c:1519 src/elflint.c:1570 +#: src/elflint.c:1523 src/elflint.c:1574 #, c-format msgid "section [%2d] '%s': cannot get relocation %zu: %s\n" msgstr "" -#: src/elflint.c:1646 +#: src/elflint.c:1650 #, c-format msgid "more than one dynamic section present\n" msgstr "" -#: src/elflint.c:1664 +#: src/elflint.c:1668 #, fuzzy, c-format msgid "" "section [%2d]: referenced as string table for section [%2d] '%s' but section " @@ -2111,427 +2118,427 @@ msgstr "" "セクション [%2d] '%s': セクション [%2d] '%s' 用の文字列テーブルとして参照され" "ていますが、タイプが SHT_STRTAB ではありません\n" -#: src/elflint.c:1672 +#: src/elflint.c:1676 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n" msgstr "" -#: src/elflint.c:1677 src/elflint.c:1966 +#: src/elflint.c:1681 src/elflint.c:1970 #, c-format msgid "section [%2d] '%s': sh_info not zero\n" msgstr "" -#: src/elflint.c:1687 +#: src/elflint.c:1691 #, c-format msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n" msgstr "" -#: src/elflint.c:1695 +#: src/elflint.c:1699 #, c-format msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n" msgstr "" -#: src/elflint.c:1702 +#: src/elflint.c:1706 #, c-format msgid "section [%2d] '%s': entry %zu: unknown tag\n" msgstr "" -#: src/elflint.c:1713 +#: src/elflint.c:1717 #, c-format msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n" msgstr "" -#: src/elflint.c:1723 +#: src/elflint.c:1727 #, c-format msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n" msgstr "" -#: src/elflint.c:1741 +#: src/elflint.c:1745 #, c-format msgid "" "section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n" msgstr "" -#: src/elflint.c:1754 +#: src/elflint.c:1758 #, c-format msgid "" "section [%2d] '%s': entry %zu: pointer does not match address of section " "[%2d] '%s' referenced by sh_link\n" msgstr "" -#: src/elflint.c:1797 +#: src/elflint.c:1801 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must point into loaded segment\n" msgstr "" -#: src/elflint.c:1812 +#: src/elflint.c:1816 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must be valid offset in section " "[%2d] '%s'\n" msgstr "" -#: src/elflint.c:1832 src/elflint.c:1860 +#: src/elflint.c:1836 src/elflint.c:1864 #, c-format msgid "section [%2d] '%s': contains %s entry but not %s\n" msgstr "" -#: src/elflint.c:1844 +#: src/elflint.c:1848 #, c-format msgid "section [%2d] '%s': mandatory tag %s not present\n" msgstr "" -#: src/elflint.c:1853 +#: src/elflint.c:1857 #, c-format msgid "section [%2d] '%s': no hash section present\n" msgstr "" -#: src/elflint.c:1868 src/elflint.c:1875 +#: src/elflint.c:1872 src/elflint.c:1879 #, c-format msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n" msgstr "" -#: src/elflint.c:1885 src/elflint.c:1889 +#: src/elflint.c:1889 src/elflint.c:1893 #, c-format msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n" msgstr "" -#: src/elflint.c:1895 +#: src/elflint.c:1899 #, c-format msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n" msgstr "" -#: src/elflint.c:1906 src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 +#: src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 src/elflint.c:1922 #, c-format msgid "section [%2d] '%s': %s tag missing in prelinked executable\n" msgstr "" -#: src/elflint.c:1930 +#: src/elflint.c:1934 #, c-format msgid "" "section [%2d] '%s': only relocatable files can have extended section index\n" msgstr "" -#: src/elflint.c:1940 +#: src/elflint.c:1944 #, c-format msgid "" "section [%2d] '%s': extended section index section not for symbol table\n" msgstr "" -#: src/elflint.c:1944 +#: src/elflint.c:1948 #, fuzzy, c-format msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n" msgstr "セクション [%2d] '%s': 不当な宛先セクションインデックス\n" -#: src/elflint.c:1949 +#: src/elflint.c:1953 #, c-format msgid "cannot get data for symbol section\n" msgstr "" -#: src/elflint.c:1952 +#: src/elflint.c:1956 #, c-format msgid "section [%2d] '%s': entry size does not match Elf32_Word\n" msgstr "" -#: src/elflint.c:1961 +#: src/elflint.c:1965 #, c-format msgid "section [%2d] '%s': extended index table too small for symbol table\n" msgstr "" -#: src/elflint.c:1976 +#: src/elflint.c:1980 #, c-format msgid "" "section [%2d] '%s': extended section index in section [%2zu] '%s' refers to " "same symbol table\n" msgstr "" -#: src/elflint.c:1994 +#: src/elflint.c:1998 #, c-format msgid "symbol 0 should have zero extended section index\n" msgstr "" -#: src/elflint.c:2006 +#: src/elflint.c:2010 #, c-format msgid "cannot get data for symbol %zu\n" msgstr "" -#: src/elflint.c:2011 +#: src/elflint.c:2015 #, c-format msgid "extended section index is % but symbol index is not XINDEX\n" msgstr "" -#: src/elflint.c:2028 src/elflint.c:2085 +#: src/elflint.c:2032 src/elflint.c:2089 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n" msgstr "" -#: src/elflint.c:2042 src/elflint.c:2099 +#: src/elflint.c:2046 src/elflint.c:2103 #, c-format msgid "section [%2d] '%s': chain array too large\n" msgstr "" -#: src/elflint.c:2056 src/elflint.c:2113 +#: src/elflint.c:2060 src/elflint.c:2117 #, c-format msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n" msgstr "" -#: src/elflint.c:2066 +#: src/elflint.c:2070 #, c-format msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n" msgstr "" -#: src/elflint.c:2123 +#: src/elflint.c:2127 #, c-format msgid "section [%2d] '%s': hash chain reference % out of bounds\n" msgstr "" -#: src/elflint.c:2136 +#: src/elflint.c:2140 #, fuzzy, c-format msgid "section [%2d] '%s': not enough data\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:2148 +#: src/elflint.c:2152 #, fuzzy, c-format msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n" msgstr "セクション [%2d] '%s': 0番目の項目にある '%s' ゼロではありません\n" -#: src/elflint.c:2164 +#: src/elflint.c:2168 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected at " "least %ld)\n" msgstr "" -#: src/elflint.c:2173 +#: src/elflint.c:2177 #, c-format msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n" msgstr "" -#: src/elflint.c:2207 +#: src/elflint.c:2211 #, c-format msgid "" "section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n" msgstr "" -#: src/elflint.c:2228 +#: src/elflint.c:2232 #, c-format msgid "" "section [%2d] '%s': symbol %u referenced in chain for bucket %zu is " "undefined\n" msgstr "" -#: src/elflint.c:2241 +#: src/elflint.c:2245 #, c-format msgid "" "section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n" msgstr "" -#: src/elflint.c:2250 +#: src/elflint.c:2254 #, fuzzy, c-format msgid "" "section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:2280 +#: src/elflint.c:2284 #, c-format msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n" msgstr "" -#: src/elflint.c:2285 +#: src/elflint.c:2289 #, c-format msgid "" "section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n" msgstr "" -#: src/elflint.c:2291 +#: src/elflint.c:2295 #, c-format msgid "section [%2d] '%s': bitmask does not match names in the hash table\n" msgstr "" -#: src/elflint.c:2304 +#: src/elflint.c:2308 #, c-format msgid "section [%2d] '%s': relocatable files cannot have hash tables\n" msgstr "" -#: src/elflint.c:2322 +#: src/elflint.c:2326 #, c-format msgid "section [%2d] '%s': hash table not for dynamic symbol table\n" msgstr "" -#: src/elflint.c:2326 +#: src/elflint.c:2330 #, fuzzy, c-format msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n" msgstr "セクション [%2d] '%s': 不当な宛先セクションインデックス\n" -#: src/elflint.c:2336 +#: src/elflint.c:2340 #, c-format msgid "section [%2d] '%s': hash table entry size incorrect\n" msgstr "" -#: src/elflint.c:2341 +#: src/elflint.c:2345 #, c-format msgid "section [%2d] '%s': not marked to be allocated\n" msgstr "" -#: src/elflint.c:2346 +#: src/elflint.c:2350 #, c-format msgid "" "section [%2d] '%s': hash table has not even room for initial administrative " "entries\n" msgstr "" -#: src/elflint.c:2395 +#: src/elflint.c:2399 #, c-format msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n" msgstr "" -#: src/elflint.c:2419 src/elflint.c:2484 src/elflint.c:2519 +#: src/elflint.c:2423 src/elflint.c:2488 src/elflint.c:2523 #, fuzzy, c-format msgid "hash section [%2zu] '%s' does not contain enough data\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:2440 +#: src/elflint.c:2444 #, fuzzy, c-format msgid "hash section [%2zu] '%s' has zero bit mask words\n" msgstr "" "\n" "セクション [%Zu] '%s' にはダンプすべきデータがありません。\n" -#: src/elflint.c:2451 src/elflint.c:2495 src/elflint.c:2532 +#: src/elflint.c:2455 src/elflint.c:2499 src/elflint.c:2536 #, fuzzy, c-format msgid "hash section [%2zu] '%s' uses too much data\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:2466 +#: src/elflint.c:2470 #, c-format msgid "" "hash section [%2zu] '%s' invalid symbol index % (max_nsyms: " "%, nentries: %\n" msgstr "" -#: src/elflint.c:2553 +#: src/elflint.c:2557 #, fuzzy, c-format msgid "hash section [%2zu] '%s' invalid sh_entsize\n" msgstr "セクション [%2d] '%s': 不当な宛先セクションタイプ\n" -#: src/elflint.c:2563 src/elflint.c:2567 +#: src/elflint.c:2567 src/elflint.c:2571 #, c-format msgid "section [%2zu] '%s': reference to symbol index 0\n" msgstr "" -#: src/elflint.c:2574 +#: src/elflint.c:2578 #, c-format msgid "" "symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash " "table in [%2zu] '%s'\n" msgstr "" -#: src/elflint.c:2586 +#: src/elflint.c:2590 #, c-format msgid "" "symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash " "table in [%2zu] '%s'\n" msgstr "" -#: src/elflint.c:2602 +#: src/elflint.c:2606 #, c-format msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n" msgstr "" -#: src/elflint.c:2622 +#: src/elflint.c:2626 #, c-format msgid "" "section [%2d] '%s': section groups only allowed in relocatable object files\n" msgstr "" -#: src/elflint.c:2633 +#: src/elflint.c:2637 #, c-format msgid "section [%2d] '%s': cannot get symbol table: %s\n" msgstr "" -#: src/elflint.c:2638 +#: src/elflint.c:2642 #, c-format msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n" msgstr "" -#: src/elflint.c:2644 +#: src/elflint.c:2648 #, c-format msgid "section [%2d] '%s': invalid symbol index in sh_info\n" msgstr "" -#: src/elflint.c:2649 +#: src/elflint.c:2653 #, c-format msgid "section [%2d] '%s': sh_flags not zero\n" msgstr "" -#: src/elflint.c:2656 +#: src/elflint.c:2660 #, c-format msgid "section [%2d] '%s': cannot get symbol for signature\n" msgstr "" -#: src/elflint.c:2660 +#: src/elflint.c:2664 #, fuzzy, c-format msgid "section [%2d] '%s': cannot get symbol name for signature\n" msgstr "セクション [%2d] '%s': シンボル %d を得られません: %s\n" -#: src/elflint.c:2665 +#: src/elflint.c:2669 #, fuzzy, c-format msgid "section [%2d] '%s': signature symbol cannot be empty string\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:2671 +#: src/elflint.c:2675 #, c-format msgid "section [%2d] '%s': sh_flags not set correctly\n" msgstr "" -#: src/elflint.c:2677 +#: src/elflint.c:2681 #, c-format msgid "section [%2d] '%s': cannot get data: %s\n" msgstr "" -#: src/elflint.c:2686 +#: src/elflint.c:2690 #, c-format msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n" msgstr "" -#: src/elflint.c:2692 +#: src/elflint.c:2696 #, c-format msgid "section [%2d] '%s': section group without flags word\n" msgstr "" -#: src/elflint.c:2700 +#: src/elflint.c:2704 #, c-format msgid "section [%2d] '%s': section group without member\n" msgstr "" -#: src/elflint.c:2704 +#: src/elflint.c:2708 #, c-format msgid "section [%2d] '%s': section group with only one member\n" msgstr "" -#: src/elflint.c:2715 +#: src/elflint.c:2719 #, c-format msgid "section [%2d] '%s': unknown section group flags\n" msgstr "" -#: src/elflint.c:2727 +#: src/elflint.c:2731 #, fuzzy, c-format msgid "section [%2d] '%s': section index %zu out of range\n" msgstr "セクション [%2d] '%s': リロケーション %zu: オフセット境界外\n" -#: src/elflint.c:2736 +#: src/elflint.c:2740 #, c-format msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n" msgstr "" -#: src/elflint.c:2743 +#: src/elflint.c:2747 #, c-format msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n" msgstr "" -#: src/elflint.c:2749 +#: src/elflint.c:2753 #, fuzzy, c-format msgid "" "section [%2d] '%s': element %zu references section [%2d] '%s' without " @@ -2540,765 +2547,765 @@ msgstr "" "セクション [%2d] '%s': シンボル %zu: 参照されるセクション [%2d] '%s' は " "SHF_TLS フラグが設定されていません\n" -#: src/elflint.c:2756 +#: src/elflint.c:2760 #, c-format msgid "section [%2d] '%s' is contained in more than one section group\n" msgstr "" -#: src/elflint.c:2946 +#: src/elflint.c:2950 #, c-format msgid "" "section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no " "dynamic symbol table\n" msgstr "" -#: src/elflint.c:2958 +#: src/elflint.c:2962 #, c-format msgid "" "section [%2d] '%s' has different number of entries than symbol table [%2d] " "'%s'\n" msgstr "" -#: src/elflint.c:2974 +#: src/elflint.c:2978 #, c-format msgid "section [%2d] '%s': symbol %d: cannot read version data\n" msgstr "" -#: src/elflint.c:2990 +#: src/elflint.c:2994 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n" msgstr "" -#: src/elflint.c:2998 +#: src/elflint.c:3002 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with version\n" msgstr "" -#: src/elflint.c:3012 +#: src/elflint.c:3016 #, c-format msgid "section [%2d] '%s': symbol %d: invalid version index %d\n" msgstr "" -#: src/elflint.c:3017 +#: src/elflint.c:3021 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for defined version\n" msgstr "" -#: src/elflint.c:3027 +#: src/elflint.c:3031 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for requested version\n" msgstr "" -#: src/elflint.c:3080 +#: src/elflint.c:3084 #, c-format msgid "more than one version reference section present\n" msgstr "" -#: src/elflint.c:3088 src/elflint.c:3235 +#: src/elflint.c:3092 src/elflint.c:3239 #, c-format msgid "section [%2d] '%s': sh_link does not link to string table\n" msgstr "" -#: src/elflint.c:3113 src/elflint.c:3289 +#: src/elflint.c:3117 src/elflint.c:3293 #, c-format msgid "section [%2d] '%s': entry %d has wrong version %d\n" msgstr "" -#: src/elflint.c:3120 src/elflint.c:3296 +#: src/elflint.c:3124 src/elflint.c:3300 #, c-format msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n" msgstr "" -#: src/elflint.c:3130 +#: src/elflint.c:3134 #, c-format msgid "section [%2d] '%s': entry %d has invalid file reference\n" msgstr "" -#: src/elflint.c:3138 +#: src/elflint.c:3142 #, c-format msgid "section [%2d] '%s': entry %d references unknown dependency\n" msgstr "" -#: src/elflint.c:3150 +#: src/elflint.c:3154 #, c-format msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n" msgstr "" -#: src/elflint.c:3158 +#: src/elflint.c:3162 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has invalid name " "reference\n" msgstr "" -#: src/elflint.c:3167 +#: src/elflint.c:3171 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: " "%#x, expected %#x\n" msgstr "" -#: src/elflint.c:3176 +#: src/elflint.c:3180 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version " "name '%s'\n" msgstr "" -#: src/elflint.c:3187 +#: src/elflint.c:3191 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n" msgstr "" -#: src/elflint.c:3204 src/elflint.c:3380 +#: src/elflint.c:3208 src/elflint.c:3384 #, c-format msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n" msgstr "" -#: src/elflint.c:3212 src/elflint.c:3388 +#: src/elflint.c:3216 src/elflint.c:3392 #, c-format msgid "" "section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says " "there are more entries\n" msgstr "" -#: src/elflint.c:3227 +#: src/elflint.c:3231 #, c-format msgid "more than one version definition section present\n" msgstr "" -#: src/elflint.c:3274 +#: src/elflint.c:3278 #, c-format msgid "section [%2d] '%s': more than one BASE definition\n" msgstr "" -#: src/elflint.c:3278 +#: src/elflint.c:3282 #, c-format msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n" msgstr "" -#: src/elflint.c:3284 +#: src/elflint.c:3288 #, c-format msgid "section [%2d] '%s': entry %d has unknown flag\n" msgstr "" -#: src/elflint.c:3311 +#: src/elflint.c:3315 #, c-format msgid "section [%2d] '%s': entry %d has invalid name reference\n" msgstr "" -#: src/elflint.c:3318 +#: src/elflint.c:3322 #, c-format msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n" msgstr "" -#: src/elflint.c:3326 +#: src/elflint.c:3330 #, c-format msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n" msgstr "" -#: src/elflint.c:3346 +#: src/elflint.c:3350 #, c-format msgid "" "section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n" msgstr "" -#: src/elflint.c:3363 +#: src/elflint.c:3367 #, c-format msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n" msgstr "" -#: src/elflint.c:3396 +#: src/elflint.c:3400 #, c-format msgid "section [%2d] '%s': no BASE definition\n" msgstr "" -#: src/elflint.c:3412 +#: src/elflint.c:3416 #, c-format msgid "section [%2d] '%s': unknown parent version '%s'\n" msgstr "" -#: src/elflint.c:3425 +#: src/elflint.c:3429 #, c-format msgid "section [%2d] '%s': empty object attributes section\n" msgstr "" -#: src/elflint.c:3446 +#: src/elflint.c:3450 #, c-format msgid "section [%2d] '%s': unrecognized attribute format\n" msgstr "" -#: src/elflint.c:3462 +#: src/elflint.c:3466 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute section\n" msgstr "" -#: src/elflint.c:3471 +#: src/elflint.c:3475 #, c-format msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n" msgstr "" -#: src/elflint.c:3483 +#: src/elflint.c:3487 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n" msgstr "" -#: src/elflint.c:3500 +#: src/elflint.c:3504 #, c-format msgid "" "section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n" msgstr "" -#: src/elflint.c:3509 +#: src/elflint.c:3513 #, c-format msgid "section [%2d] '%s': offset %zu: truncated attribute section\n" msgstr "" -#: src/elflint.c:3518 +#: src/elflint.c:3522 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute subsection\n" msgstr "" -#: src/elflint.c:3533 +#: src/elflint.c:3537 #, c-format msgid "" "section [%2d] '%s': offset %zu: invalid length in attribute subsection\n" msgstr "" #. Tag_File -#: src/elflint.c:3544 +#: src/elflint.c:3548 #, c-format msgid "" "section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n" msgstr "" -#: src/elflint.c:3562 +#: src/elflint.c:3566 #, c-format msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n" msgstr "" -#: src/elflint.c:3573 +#: src/elflint.c:3577 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n" msgstr "" -#: src/elflint.c:3586 +#: src/elflint.c:3590 #, c-format msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n" msgstr "" -#: src/elflint.c:3590 +#: src/elflint.c:3594 #, c-format msgid "" "section [%2d] '%s': offset %zu: unrecognized %s attribute value %\n" msgstr "" -#: src/elflint.c:3600 +#: src/elflint.c:3604 #, c-format msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n" msgstr "" -#: src/elflint.c:3606 +#: src/elflint.c:3610 #, c-format msgid "" "section [%2d] '%s': offset %zu: extra bytes after last attribute section\n" msgstr "" -#: src/elflint.c:3695 +#: src/elflint.c:3699 #, c-format msgid "cannot get section header of zeroth section\n" msgstr "" -#: src/elflint.c:3699 +#: src/elflint.c:3703 #, c-format msgid "zeroth section has nonzero name\n" msgstr "" -#: src/elflint.c:3701 +#: src/elflint.c:3705 #, c-format msgid "zeroth section has nonzero type\n" msgstr "" -#: src/elflint.c:3703 +#: src/elflint.c:3707 #, c-format msgid "zeroth section has nonzero flags\n" msgstr "" -#: src/elflint.c:3705 +#: src/elflint.c:3709 #, c-format msgid "zeroth section has nonzero address\n" msgstr "" -#: src/elflint.c:3707 +#: src/elflint.c:3711 #, c-format msgid "zeroth section has nonzero offset\n" msgstr "" -#: src/elflint.c:3709 +#: src/elflint.c:3713 #, c-format msgid "zeroth section has nonzero align value\n" msgstr "" -#: src/elflint.c:3711 +#: src/elflint.c:3715 #, c-format msgid "zeroth section has nonzero entry size value\n" msgstr "" -#: src/elflint.c:3714 +#: src/elflint.c:3718 #, c-format msgid "" "zeroth section has nonzero size value while ELF header has nonzero shnum " "value\n" msgstr "" -#: src/elflint.c:3718 +#: src/elflint.c:3722 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " "overflow in shstrndx\n" msgstr "" -#: src/elflint.c:3722 +#: src/elflint.c:3726 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " "overflow in phnum\n" msgstr "" -#: src/elflint.c:3740 +#: src/elflint.c:3744 #, c-format msgid "cannot get section header for section [%2zu] '%s': %s\n" msgstr "" -#: src/elflint.c:3749 +#: src/elflint.c:3753 #, c-format msgid "section [%2zu]: invalid name\n" msgstr "" -#: src/elflint.c:3776 +#: src/elflint.c:3780 #, c-format msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n" msgstr "" -#: src/elflint.c:3794 +#: src/elflint.c:3798 #, c-format msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n" msgstr "" -#: src/elflint.c:3812 +#: src/elflint.c:3816 #, c-format msgid "" "section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n" msgstr "" -#: src/elflint.c:3830 +#: src/elflint.c:3834 #, c-format msgid "section [%2zu] '%s' present in object file\n" msgstr "" -#: src/elflint.c:3836 src/elflint.c:3868 +#: src/elflint.c:3840 src/elflint.c:3872 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n" msgstr "" -#: src/elflint.c:3841 src/elflint.c:3873 +#: src/elflint.c:3845 src/elflint.c:3877 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable " "segments\n" msgstr "" -#: src/elflint.c:3849 +#: src/elflint.c:3853 #, c-format msgid "" "section [%2zu] '%s' is extension section index table in non-object file\n" msgstr "" -#: src/elflint.c:3892 +#: src/elflint.c:3896 #, c-format msgid "section [%2zu] '%s': size not multiple of entry size\n" msgstr "" -#: src/elflint.c:3897 +#: src/elflint.c:3901 #, c-format msgid "cannot get section header\n" msgstr "" -#: src/elflint.c:3907 +#: src/elflint.c:3911 #, c-format msgid "section [%2zu] '%s' has unsupported type %d\n" msgstr "" -#: src/elflint.c:3922 +#: src/elflint.c:3926 #, c-format msgid "" "section [%2zu] '%s' contains invalid processor-specific flag(s) %#\n" msgstr "" -#: src/elflint.c:3929 +#: src/elflint.c:3933 #, c-format msgid "section [%2zu] '%s' contains unknown flag(s) %#\n" msgstr "" -#: src/elflint.c:3937 +#: src/elflint.c:3941 #, c-format msgid "section [%2zu] '%s': thread-local data sections address not zero\n" msgstr "" -#: src/elflint.c:3947 +#: src/elflint.c:3951 #, fuzzy, c-format msgid "section [%2zu] '%s': allocated section cannot be compressed\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:3952 +#: src/elflint.c:3956 #, fuzzy, c-format msgid "section [%2zu] '%s': nobits section cannot be compressed\n" msgstr "セクション [%2d] '%s': セクションデータを得られません\n" -#: src/elflint.c:3958 +#: src/elflint.c:3962 #, c-format msgid "" "section [%2zu] '%s': compressed section with no compression header: %s\n" msgstr "" -#: src/elflint.c:3964 +#: src/elflint.c:3968 #, c-format msgid "section [%2zu] '%s': invalid section reference in link value\n" msgstr "" -#: src/elflint.c:3969 +#: src/elflint.c:3973 #, c-format msgid "section [%2zu] '%s': invalid section reference in info value\n" msgstr "" -#: src/elflint.c:3976 +#: src/elflint.c:3980 #, c-format msgid "section [%2zu] '%s': strings flag set without merge flag\n" msgstr "" -#: src/elflint.c:3981 +#: src/elflint.c:3985 #, c-format msgid "section [%2zu] '%s': merge flag set but entry size is zero\n" msgstr "" -#: src/elflint.c:4000 +#: src/elflint.c:4004 #, c-format msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n" msgstr "" -#: src/elflint.c:4009 +#: src/elflint.c:4013 #, c-format msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n" msgstr "" -#: src/elflint.c:4016 +#: src/elflint.c:4020 #, c-format msgid "section [%2zu] '%s' is both executable and writable\n" msgstr "" -#: src/elflint.c:4047 +#: src/elflint.c:4051 #, c-format msgid "" "section [%2zu] '%s' not fully contained in segment of program header entry " "%d\n" msgstr "" -#: src/elflint.c:4057 +#: src/elflint.c:4061 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " "program header entry %d\n" msgstr "" -#: src/elflint.c:4083 +#: src/elflint.c:4087 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " "program header entry %d and file contents is non-zero\n" msgstr "" -#: src/elflint.c:4094 +#: src/elflint.c:4098 #, c-format msgid "" "section [%2zu] '%s' has not type NOBITS but is not read from the file in " "segment of program header entry %d\n" msgstr "" -#: src/elflint.c:4105 +#: src/elflint.c:4109 #, c-format msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n" msgstr "" -#: src/elflint.c:4115 +#: src/elflint.c:4119 #, c-format msgid "section [%2zu] '%s' is writable in unwritable segment %d\n" msgstr "" -#: src/elflint.c:4125 +#: src/elflint.c:4129 #, c-format msgid "" "section [%2zu] '%s': alloc flag set but section not in any loaded segment\n" msgstr "" -#: src/elflint.c:4131 +#: src/elflint.c:4135 #, c-format msgid "" "section [%2zu] '%s': ELF header says this is the section header string table " "but type is not SHT_TYPE\n" msgstr "" -#: src/elflint.c:4139 +#: src/elflint.c:4143 #, c-format msgid "" "section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n" msgstr "" -#: src/elflint.c:4190 +#: src/elflint.c:4194 #, c-format msgid "more than one version symbol table present\n" msgstr "" -#: src/elflint.c:4213 +#: src/elflint.c:4217 #, c-format msgid "INTERP program header entry but no .interp section\n" msgstr "" -#: src/elflint.c:4224 +#: src/elflint.c:4228 #, c-format msgid "" "loadable segment [%u] is executable but contains no executable sections\n" msgstr "" -#: src/elflint.c:4230 +#: src/elflint.c:4234 #, c-format msgid "loadable segment [%u] is writable but contains no writable sections\n" msgstr "" -#: src/elflint.c:4241 +#: src/elflint.c:4245 #, c-format msgid "" "no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section " "exist\n" msgstr "" -#: src/elflint.c:4254 +#: src/elflint.c:4258 #, c-format msgid "duplicate version index %d\n" msgstr "" -#: src/elflint.c:4268 +#: src/elflint.c:4272 #, c-format msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n" msgstr "" -#: src/elflint.c:4317 +#: src/elflint.c:4321 #, c-format msgid "phdr[%d]: unknown core file note type % at offset %\n" msgstr "" -#: src/elflint.c:4321 +#: src/elflint.c:4325 #, c-format msgid "" "section [%2d] '%s': unknown core file note type % at offset %zu\n" msgstr "" -#: src/elflint.c:4370 +#: src/elflint.c:4374 #, c-format msgid "" "phdr[%d]: unknown object file note type % with owner name '%s' at " "offset %zu\n" msgstr "" -#: src/elflint.c:4375 +#: src/elflint.c:4379 #, c-format msgid "" "section [%2d] '%s': unknown object file note type % with owner name " "'%s' at offset %zu\n" msgstr "" -#: src/elflint.c:4394 +#: src/elflint.c:4398 #, c-format msgid "phdr[%d]: no note entries defined for the type of file\n" msgstr "" -#: src/elflint.c:4414 +#: src/elflint.c:4418 #, c-format msgid "phdr[%d]: cannot get content of note section: %s\n" msgstr "" -#: src/elflint.c:4417 +#: src/elflint.c:4421 #, c-format msgid "phdr[%d]: extra % bytes after last note\n" msgstr "" -#: src/elflint.c:4438 +#: src/elflint.c:4442 #, c-format msgid "section [%2d] '%s': no note entries defined for the type of file\n" msgstr "" -#: src/elflint.c:4445 +#: src/elflint.c:4449 #, c-format msgid "section [%2d] '%s': cannot get content of note section\n" msgstr "" -#: src/elflint.c:4448 +#: src/elflint.c:4452 #, c-format msgid "section [%2d] '%s': extra % bytes after last note\n" msgstr "" -#: src/elflint.c:4466 +#: src/elflint.c:4470 #, c-format msgid "" "only executables, shared objects, and core files can have program headers\n" msgstr "" -#: src/elflint.c:4481 +#: src/elflint.c:4485 #, c-format msgid "cannot get program header entry %d: %s\n" msgstr "" -#: src/elflint.c:4490 +#: src/elflint.c:4499 #, c-format msgid "program header entry %d: unknown program header entry type %#\n" msgstr "" -#: src/elflint.c:4501 +#: src/elflint.c:4510 #, c-format msgid "more than one INTERP entry in program header\n" msgstr "" -#: src/elflint.c:4509 +#: src/elflint.c:4518 #, c-format msgid "more than one TLS entry in program header\n" msgstr "" -#: src/elflint.c:4516 +#: src/elflint.c:4525 #, c-format msgid "static executable cannot have dynamic sections\n" msgstr "" -#: src/elflint.c:4530 +#: src/elflint.c:4539 #, c-format msgid "dynamic section reference in program header has wrong offset\n" msgstr "" -#: src/elflint.c:4533 +#: src/elflint.c:4542 #, c-format msgid "dynamic section size mismatch in program and section header\n" msgstr "" -#: src/elflint.c:4543 +#: src/elflint.c:4552 #, c-format msgid "more than one GNU_RELRO entry in program header\n" msgstr "" -#: src/elflint.c:4564 +#: src/elflint.c:4573 #, c-format msgid "loadable segment GNU_RELRO applies to is not writable\n" msgstr "" -#: src/elflint.c:4575 +#: src/elflint.c:4584 #, c-format msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n" msgstr "" -#: src/elflint.c:4582 +#: src/elflint.c:4591 #, c-format msgid "" "GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n" msgstr "" -#: src/elflint.c:4591 src/elflint.c:4614 +#: src/elflint.c:4600 src/elflint.c:4623 #, c-format msgid "%s segment not contained in a loaded segment\n" msgstr "" -#: src/elflint.c:4620 +#: src/elflint.c:4629 #, c-format msgid "program header offset in ELF header and PHDR entry do not match" msgstr "" -#: src/elflint.c:4647 +#: src/elflint.c:4656 #, c-format msgid "call frame search table reference in program header has wrong offset\n" msgstr "" -#: src/elflint.c:4650 +#: src/elflint.c:4659 #, c-format msgid "call frame search table size mismatch in program and section header\n" msgstr "" -#: src/elflint.c:4663 +#: src/elflint.c:4672 #, c-format msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n" msgstr "" -#: src/elflint.c:4671 +#: src/elflint.c:4680 #, c-format msgid "call frame search table must be allocated\n" msgstr "" -#: src/elflint.c:4674 +#: src/elflint.c:4683 #, c-format msgid "section [%2zu] '%s' must be allocated\n" msgstr "" -#: src/elflint.c:4678 +#: src/elflint.c:4687 #, c-format msgid "call frame search table must not be writable\n" msgstr "" -#: src/elflint.c:4681 +#: src/elflint.c:4690 #, c-format msgid "section [%2zu] '%s' must not be writable\n" msgstr "" -#: src/elflint.c:4686 +#: src/elflint.c:4695 #, c-format msgid "call frame search table must not be executable\n" msgstr "" -#: src/elflint.c:4689 +#: src/elflint.c:4698 #, c-format msgid "section [%2zu] '%s' must not be executable\n" msgstr "" -#: src/elflint.c:4700 +#: src/elflint.c:4709 #, c-format msgid "program header entry %d: file size greater than memory size\n" msgstr "" -#: src/elflint.c:4707 +#: src/elflint.c:4716 #, c-format msgid "program header entry %d: alignment not a power of 2\n" msgstr "" -#: src/elflint.c:4710 +#: src/elflint.c:4719 #, c-format msgid "" "program header entry %d: file offset and virtual address not module of " "alignment\n" msgstr "" -#: src/elflint.c:4723 +#: src/elflint.c:4732 #, c-format msgid "" "executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME " "program header entry" msgstr "" -#: src/elflint.c:4757 +#: src/elflint.c:4766 #, c-format msgid "cannot read ELF header: %s\n" msgstr "" -#: src/elflint.c:4783 +#: src/elflint.c:4792 #, c-format msgid "text relocation flag set but not needed\n" msgstr "" diff --git a/libdrgn/elfutils/po/pl.po b/libdrgn/elfutils/po/pl.po index 54a016411..63e09a37f 100644 --- a/libdrgn/elfutils/po/pl.po +++ b/libdrgn/elfutils/po/pl.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: elfutils\n" "Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n" -"POT-Creation-Date: 2019-11-26 09:48+0100\n" +"POT-Creation-Date: 2020-03-30 12:56+0200\n" "PO-Revision-Date: 2016-12-29 17:48+0100\n" "Last-Translator: Piotr Drąg \n" "Language-Team: Polish \n" @@ -526,7 +526,7 @@ msgstr "Brak zaplecza" #: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:77 #: libebl/eblobjnotetypename.c:109 libebl/eblobjnotetypename.c:130 #: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83 -#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:79 +#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:85 msgid "" msgstr "" @@ -1673,14 +1673,14 @@ msgid "" msgstr "" "sekcja [%2d] „%s”: grupa sekcji [%2zu] „%s” nie poprzedza elementu grupy\n" -#: src/elflint.c:610 src/elflint.c:1494 src/elflint.c:1545 src/elflint.c:1651 -#: src/elflint.c:1987 src/elflint.c:2313 src/elflint.c:2932 src/elflint.c:3095 -#: src/elflint.c:3243 src/elflint.c:3433 src/elflint.c:4431 +#: src/elflint.c:610 src/elflint.c:1498 src/elflint.c:1549 src/elflint.c:1655 +#: src/elflint.c:1991 src/elflint.c:2317 src/elflint.c:2936 src/elflint.c:3099 +#: src/elflint.c:3247 src/elflint.c:3437 src/elflint.c:4435 #, c-format msgid "section [%2d] '%s': cannot get section data\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać danych sekcji\n" -#: src/elflint.c:623 src/elflint.c:1658 +#: src/elflint.c:623 src/elflint.c:1662 #, c-format msgid "" "section [%2d] '%s': referenced as string table for section [%2d] '%s' but " @@ -1703,33 +1703,40 @@ msgstr "" msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n" msgstr "sekcja [%2u] „%s”: rozmiar wpisu nie zgadza się z ElfXX_Sym\n" -#: src/elflint.c:667 +#: src/elflint.c:662 +#, fuzzy, c-format +msgid "" +"section [%2u] '%s': number of local entries in 'st_info' larger than table " +"size\n" +msgstr "sekcja [%2d] „%s”: brak określonych wpisów notatek dla typu pliku\n" + +#: src/elflint.c:671 #, c-format msgid "section [%2d] '%s': cannot get symbol %d: %s\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać symbolu %d: %s\n" -#: src/elflint.c:672 src/elflint.c:675 src/elflint.c:678 src/elflint.c:681 -#: src/elflint.c:684 src/elflint.c:687 +#: src/elflint.c:676 src/elflint.c:679 src/elflint.c:682 src/elflint.c:685 +#: src/elflint.c:688 src/elflint.c:691 #, c-format msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n" msgstr "sekcja [%2d] „%s”: „%s” w zerowym wpisie nie jest zerem\n" -#: src/elflint.c:690 +#: src/elflint.c:694 #, c-format msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n" msgstr "sekcja [%2d] „%s”: XINDEX dla zerowego wpisu nie jest zerem\n" -#: src/elflint.c:700 +#: src/elflint.c:704 #, c-format msgid "section [%2d] '%s': cannot get symbol %zu: %s\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać symbolu %zu: %s\n" -#: src/elflint.c:709 +#: src/elflint.c:713 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid name value\n" msgstr "sekcja [%2d] „%s”: symbol %zu: nieprawidłowa wartość nazwy\n" -#: src/elflint.c:724 +#: src/elflint.c:728 #, c-format msgid "" "section [%2d] '%s': symbol %zu: too large section index but no extended " @@ -1738,7 +1745,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: za duży indeks sekcji, ale nie ma sekcji " "rozszerzonych indeksów sekcji\n" -#: src/elflint.c:730 +#: src/elflint.c:734 #, c-format msgid "" "section [%2d] '%s': symbol %zu: XINDEX used for index which would fit in " @@ -1748,28 +1755,28 @@ msgstr "" "się w st_shndx (%)\n" #. || sym->st_shndx > SHN_HIRESERVE always false -#: src/elflint.c:742 +#: src/elflint.c:746 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid section index\n" msgstr "sekcja [%2d] „%s”: symbol %zu: nieprawidłowy indeks sekcji\n" -#: src/elflint.c:750 +#: src/elflint.c:754 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown type\n" msgstr "sekcja [%2d] „%s”: symbol %zu: nieznany typ\n" -#: src/elflint.c:756 +#: src/elflint.c:760 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown symbol binding\n" msgstr "sekcja [%2d] „%s”: symbol %zu: nieznane dowiązanie symbolu\n" -#: src/elflint.c:761 +#: src/elflint.c:765 #, c-format msgid "section [%2d] '%s': symbol %zu: unique symbol not of object type\n" msgstr "" "sekcja [%2d] „%s”: symbol %zu: unikalny symbol nie jest typem obiektu\n" -#: src/elflint.c:769 +#: src/elflint.c:773 #, c-format msgid "" "section [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n" @@ -1777,23 +1784,23 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: COMMON jest dozwolone tylko w plikach " "relokowalnych\n" -#: src/elflint.c:773 +#: src/elflint.c:777 #, c-format msgid "section [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n" msgstr "sekcja [%2d] „%s”: symbol %zu: lokalne symbole COMMON to nonsens\n" -#: src/elflint.c:777 +#: src/elflint.c:781 #, c-format msgid "" "section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n" msgstr "sekcja [%2d] „%s”: symbol %zu: funkcja w sekcji COMMON to nonsens\n" -#: src/elflint.c:828 +#: src/elflint.c:832 #, c-format msgid "section [%2d] '%s': symbol %zu: st_value out of bounds\n" msgstr "sekcja [%2d] „%s”: symbol %zu: st_value spoza zakresu\n" -#: src/elflint.c:834 src/elflint.c:859 src/elflint.c:908 +#: src/elflint.c:838 src/elflint.c:863 src/elflint.c:912 #, c-format msgid "" "section [%2d] '%s': symbol %zu does not fit completely in referenced section " @@ -1802,7 +1809,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu nie mieści się w całości we wskazywanej sekcji " "[%2d] „%s”\n" -#: src/elflint.c:843 +#: src/elflint.c:847 #, c-format msgid "" "section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have " @@ -1811,7 +1818,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: wskazywana sekcja [%2d] „%s” nie ma " "ustawionej flagi SHF_TLS\n" -#: src/elflint.c:853 src/elflint.c:901 +#: src/elflint.c:857 src/elflint.c:905 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section " @@ -1820,7 +1827,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: st_value spoza zakresu wskazywanej sekcji " "[%2d] „%s”\n" -#: src/elflint.c:880 +#: src/elflint.c:884 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n" @@ -1828,7 +1835,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: symbol TLS, ale brak wpisu TLS nagłówka " "programu\n" -#: src/elflint.c:886 +#: src/elflint.c:890 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program " @@ -1837,7 +1844,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: symbol TLS, ale nie można uzyskać wpisu TLS " "nagłówka programu\n" -#: src/elflint.c:894 +#: src/elflint.c:898 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] " @@ -1845,7 +1852,7 @@ msgid "" msgstr "" "sekcja [%2d] „%s”: symbol %zu: st_value pomija wskazywaną sekcję [%2d] „%s”\n" -#: src/elflint.c:921 +#: src/elflint.c:925 #, c-format msgid "" "section [%2d] '%s': symbol %zu: local symbol outside range described in " @@ -1854,7 +1861,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: lokalny symbol spoza zakresu określonego " "w sh_info\n" -#: src/elflint.c:928 +#: src/elflint.c:932 #, c-format msgid "" "section [%2d] '%s': symbol %zu: non-local symbol outside range described in " @@ -1863,12 +1870,12 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: nielokalny symbol spoza zakresu określonego " "w sh_info\n" -#: src/elflint.c:935 +#: src/elflint.c:939 #, c-format msgid "section [%2d] '%s': symbol %zu: non-local section symbol\n" msgstr "sekcja [%2d] „%s”: symbol %zu: nielokalny symbol sekcji\n" -#: src/elflint.c:985 +#: src/elflint.c:989 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section " @@ -1877,7 +1884,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol _GLOBAL_OFFSET_TABLE_ odnosi się do błędnej sekcji " "[%2d]\n" -#: src/elflint.c:992 +#: src/elflint.c:996 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] " @@ -1889,7 +1896,7 @@ msgstr "" #. This test is more strict than the psABIs which #. usually allow the symbol to be in the middle of #. the .got section, allowing negative offsets. -#: src/elflint.c:1008 +#: src/elflint.c:1012 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %# does not " @@ -1898,7 +1905,7 @@ msgstr "" "sekcja [%2d] „%s”: wartość symbolu _GLOBAL_OFFSET_TABLE_ %# nie " "pasuje do adresu sekcji %s %#\n" -#: src/elflint.c:1015 +#: src/elflint.c:1019 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size % does not " @@ -1907,7 +1914,7 @@ msgstr "" "sekcja [%2d] „%s”: rozmiar symbolu _GLOBAL_OFFSET_TABLE_ % nie " "pasuje do rozmiaru sekcji %s %\n" -#: src/elflint.c:1023 +#: src/elflint.c:1027 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got " @@ -1916,7 +1923,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol _GLOBAL_OFFSET_TABLE_ istnieje, ale brak sekcji ." "got\n" -#: src/elflint.c:1039 +#: src/elflint.c:1043 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC_ symbol value %# does not match dynamic " @@ -1925,7 +1932,7 @@ msgstr "" "sekcja [%2d] „%s”: wartość symbolu _DYNAMIC_ %# nie pasuje do adresu " "segmentu dynamicznego %#\n" -#: src/elflint.c:1046 +#: src/elflint.c:1050 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC symbol size % does not match dynamic " @@ -1934,7 +1941,7 @@ msgstr "" "sekcja [%2d] „%s”: rozmiar symbolu _DYNAMIC_ % nie pasuje do " "rozmiaru segmentu dynamicznego %\n" -#: src/elflint.c:1059 +#: src/elflint.c:1063 #, c-format msgid "" "section [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-" @@ -1943,27 +1950,27 @@ msgstr "" "sekcja [%2d] „%s”: symbol %zu: symbol w dynamicznej tabeli symboli " "z niedomyślną widocznością\n" -#: src/elflint.c:1063 +#: src/elflint.c:1067 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown bit set in st_other\n" msgstr "sekcja [%2d] „%s”: symbol %zu: ustawiono nieznany bit w st_other\n" -#: src/elflint.c:1101 +#: src/elflint.c:1105 #, c-format msgid "section [%2d] '%s': cannot get section data.\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać danych sekcji.\n" -#: src/elflint.c:1117 +#: src/elflint.c:1121 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n" msgstr "sekcja [%2d] „%s”: DT_RELCOUNT użyte dla tej sekcji RELA\n" -#: src/elflint.c:1128 src/elflint.c:1181 +#: src/elflint.c:1132 src/elflint.c:1185 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n" msgstr "sekcja [%2d] „%s”: DT_RELCOUNT %d za duże dla tej sekcji\n" -#: src/elflint.c:1153 src/elflint.c:1206 +#: src/elflint.c:1157 src/elflint.c:1210 #, c-format msgid "" "section [%2d] '%s': relative relocations after index %d as specified by " @@ -1972,7 +1979,7 @@ msgstr "" "sekcja [%2d] „%s”: relokacje względne po indeksie %d podanym przez " "DT_RELCOUNT\n" -#: src/elflint.c:1159 src/elflint.c:1212 +#: src/elflint.c:1163 src/elflint.c:1216 #, c-format msgid "" "section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT " @@ -1981,50 +1988,50 @@ msgstr "" "sekcja [%2d] „%s”: relokacja bezwzględna pod indeksem %zu; DT_RELCOUNT podał " "%d relokacji względnych\n" -#: src/elflint.c:1171 +#: src/elflint.c:1175 #, c-format msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n" msgstr "sekcja [%2d] „%s”: DT_RELACOUNT użyte dla tej sekcji REL\n" -#: src/elflint.c:1254 +#: src/elflint.c:1258 #, c-format msgid "section [%2d] '%s': invalid destination section index\n" msgstr "sekcja [%2d] „%s”: nieprawidłowy indeks sekcji docelowej\n" -#: src/elflint.c:1266 +#: src/elflint.c:1270 #, c-format msgid "section [%2d] '%s': invalid destination section type\n" msgstr "sekcja [%2d] „%s”: nieprawidłowy typ sekcji docelowej\n" -#: src/elflint.c:1274 +#: src/elflint.c:1278 #, c-format msgid "section [%2d] '%s': sh_info should be zero\n" msgstr "sekcja [%2d] „%s”: sh_info powinno wynosić zero\n" -#: src/elflint.c:1282 +#: src/elflint.c:1286 #, c-format msgid "" "section [%2d] '%s': no relocations for merge-able string sections possible\n" msgstr "" "sekcja [%2d] „%s”: relokacje dla sekcji złączalnych ciągów są niemożliwe\n" -#: src/elflint.c:1290 +#: src/elflint.c:1294 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n" msgstr "sekcja [%2d] „%s”: rozmiar wpisu sekcji nie zgadza się z ElfXX_Rela\n" -#: src/elflint.c:1350 +#: src/elflint.c:1354 #, c-format msgid "text relocation flag set but there is no read-only segment\n" msgstr "" "flaga relokacji tekstu jest ustawiona, ale nie ma segmentu tylko do odczytu\n" -#: src/elflint.c:1377 +#: src/elflint.c:1381 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid type\n" msgstr "sekcja [%2d] „%s”: relokacja %zu: nieprawidłowy typ\n" -#: src/elflint.c:1385 +#: src/elflint.c:1389 #, c-format msgid "" "section [%2d] '%s': relocation %zu: relocation type invalid for the file " @@ -2033,12 +2040,12 @@ msgstr "" "sekcja [%2d] „%s”: relokacja %zu: typ relokacji nieprawidłowy dla tego typu " "pliku\n" -#: src/elflint.c:1393 +#: src/elflint.c:1397 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n" msgstr "sekcja [%2d] „%s”: relokacja %zu: nieprawidłowy indeks symbolu\n" -#: src/elflint.c:1411 +#: src/elflint.c:1415 #, c-format msgid "" "section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can " @@ -2047,12 +2054,12 @@ msgstr "" "sekcja [%2d] „%s”: relokacja %zu: z %s można użyć tylko symbolu " "„_GLOBAL_OFFSET_TABLE_”\n" -#: src/elflint.c:1428 +#: src/elflint.c:1432 #, c-format msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n" msgstr "sekcja [%2d] „%s”: relokacja %zu: offset spoza zakresu\n" -#: src/elflint.c:1443 +#: src/elflint.c:1447 #, c-format msgid "" "section [%2d] '%s': relocation %zu: copy relocation against symbol of type " @@ -2060,7 +2067,7 @@ msgid "" msgstr "" "sekcja [%2d] „%s”: relokacja %zu: relokacja kopii względem symbolu typu %s\n" -#: src/elflint.c:1464 +#: src/elflint.c:1468 #, c-format msgid "" "section [%2d] '%s': relocation %zu: read-only section modified but text " @@ -2069,23 +2076,23 @@ msgstr "" "sekcja [%2d] „%s”: relokacja %zu: sekcja tylko do odczytu została " "zmodyfikowana, ale nie ustawiono flagi relokacji tekstu\n" -#: src/elflint.c:1479 +#: src/elflint.c:1483 #, c-format msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n" msgstr "" "sekcja [%2d] „%s”: relokacje względem wczytanych i niewczytanych danych\n" -#: src/elflint.c:1519 src/elflint.c:1570 +#: src/elflint.c:1523 src/elflint.c:1574 #, c-format msgid "section [%2d] '%s': cannot get relocation %zu: %s\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać relokacji %zu: %s\n" -#: src/elflint.c:1646 +#: src/elflint.c:1650 #, c-format msgid "more than one dynamic section present\n" msgstr "obecna jest więcej niż jedna sekcja dynamiczna\n" -#: src/elflint.c:1664 +#: src/elflint.c:1668 #, c-format msgid "" "section [%2d]: referenced as string table for section [%2d] '%s' but section " @@ -2094,43 +2101,43 @@ msgstr "" "sekcja [%2d]: wskazane jako tabela ciągów dla sekcji [%2d] „%s”, ale wartość " "dowiązania sekcji jest nieprawidłowa\n" -#: src/elflint.c:1672 +#: src/elflint.c:1676 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n" msgstr "sekcja [%2d] „%s”: rozmiar wpisu sekcji nie zgadza się z ElfXX_Dyn\n" -#: src/elflint.c:1677 src/elflint.c:1966 +#: src/elflint.c:1681 src/elflint.c:1970 #, c-format msgid "section [%2d] '%s': sh_info not zero\n" msgstr "sekcja [%2d] „%s”: sh_info nie wynosi zero\n" -#: src/elflint.c:1687 +#: src/elflint.c:1691 #, c-format msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n" msgstr "" "sekcja [%2d] „%s”: nie można uzyskać wpisu %zu sekcji dynamicznej: %s\n" -#: src/elflint.c:1695 +#: src/elflint.c:1699 #, c-format msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n" msgstr "sekcja [%2d] „%s”: wpisy nie-DT_NULL występują po wpisie DT_NULL\n" -#: src/elflint.c:1702 +#: src/elflint.c:1706 #, c-format msgid "section [%2d] '%s': entry %zu: unknown tag\n" msgstr "sekcja [%2d] „%s”: wpis %zu: nieznany znacznik\n" -#: src/elflint.c:1713 +#: src/elflint.c:1717 #, c-format msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n" msgstr "sekcja [%2d] „%s”: wpis %zu: więcej niż jeden wpis ze znacznikiem %s\n" -#: src/elflint.c:1723 +#: src/elflint.c:1727 #, c-format msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n" msgstr "sekcja [%2d] „%s”: wpis %zu: użyto znacznika %s poziomu 2\n" -#: src/elflint.c:1741 +#: src/elflint.c:1745 #, c-format msgid "" "section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n" @@ -2138,7 +2145,7 @@ msgstr "" "sekcja [%2d] „%s”: wpis %zu: wartość DT_PLTREL musi wynosić DT_REL lub " "DT_RELA\n" -#: src/elflint.c:1754 +#: src/elflint.c:1758 #, c-format msgid "" "section [%2d] '%s': entry %zu: pointer does not match address of section " @@ -2147,14 +2154,14 @@ msgstr "" "sekcja [%2d] „%s”: wpis %zu: wskaźnik nie pasuje do adresu sekcji [%2d] „%s” " "wskazywanej przez sh_link\n" -#: src/elflint.c:1797 +#: src/elflint.c:1801 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must point into loaded segment\n" msgstr "" "sekcja [%2d] „%s”: wpis %zu: wartość %s musi wskazywać na wczytany segment\n" -#: src/elflint.c:1812 +#: src/elflint.c:1816 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must be valid offset in section " @@ -2163,48 +2170,48 @@ msgstr "" "sekcja [%2d] „%s”: wpis %zu: wartość %s musi być prawidłowym offsetem " "w sekcji [%2d] „%s”\n" -#: src/elflint.c:1832 src/elflint.c:1860 +#: src/elflint.c:1836 src/elflint.c:1864 #, c-format msgid "section [%2d] '%s': contains %s entry but not %s\n" msgstr "sekcja [%2d] „%s”: zawiera wpis %s, ale nie %s\n" -#: src/elflint.c:1844 +#: src/elflint.c:1848 #, c-format msgid "section [%2d] '%s': mandatory tag %s not present\n" msgstr "sekcja [%2d] „%s”: brak obowiązkowego znacznika %s\n" -#: src/elflint.c:1853 +#: src/elflint.c:1857 #, c-format msgid "section [%2d] '%s': no hash section present\n" msgstr "sekcja [%2d] „%s”: brak sekcji skrótów\n" -#: src/elflint.c:1868 src/elflint.c:1875 +#: src/elflint.c:1872 src/elflint.c:1879 #, c-format msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n" msgstr "sekcja [%2d] „%s”: nie wszystkie z %s, %s i %s są obecne\n" -#: src/elflint.c:1885 src/elflint.c:1889 +#: src/elflint.c:1889 src/elflint.c:1893 #, c-format msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n" msgstr "" "sekcja [%2d] „%s”: brak znacznika %s w DSO oznaczonym podczas wstępnej " "konsolidacji\n" -#: src/elflint.c:1895 +#: src/elflint.c:1899 #, c-format msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n" msgstr "" "sekcja [%2d] „%s”: plik nie-DSO oznaczony jako zależność podczas wstępnej " "konsolidacji\n" -#: src/elflint.c:1906 src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 +#: src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 src/elflint.c:1922 #, c-format msgid "section [%2d] '%s': %s tag missing in prelinked executable\n" msgstr "" "sekcja [%2d] „%s”: brak znacznika %s we wstępnie konsolidowanym pliku " "wykonywalnym\n" -#: src/elflint.c:1930 +#: src/elflint.c:1934 #, c-format msgid "" "section [%2d] '%s': only relocatable files can have extended section index\n" @@ -2212,7 +2219,7 @@ msgstr "" "sekcja [%2d] „%s”: tylko pliki relokowalne mogą mieć rozszerzoną sekcję " "indeksów\n" -#: src/elflint.c:1940 +#: src/elflint.c:1944 #, c-format msgid "" "section [%2d] '%s': extended section index section not for symbol table\n" @@ -2220,31 +2227,31 @@ msgstr "" "sekcja [%2d] „%s”: sekcja rozszerzonych indeksów sekcji nie dla tabeli " "symboli\n" -#: src/elflint.c:1944 +#: src/elflint.c:1948 #, c-format msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n" msgstr "" "sekcja [%2d] „%s”: rozszerzony indeks sekcji sh_link [%2d] jest " "nieprawidłowy\n" -#: src/elflint.c:1949 +#: src/elflint.c:1953 #, c-format msgid "cannot get data for symbol section\n" msgstr "nie można uzyskać danych dla sekcji symboli\n" -#: src/elflint.c:1952 +#: src/elflint.c:1956 #, c-format msgid "section [%2d] '%s': entry size does not match Elf32_Word\n" msgstr "sekcja [%2d] „%s”: rozmiar wpisu nie zgadza się z Elf32_Word\n" -#: src/elflint.c:1961 +#: src/elflint.c:1965 #, c-format msgid "section [%2d] '%s': extended index table too small for symbol table\n" msgstr "" "sekcja [%2d] „%s”: tabela rozszerzonych indeksów jest za mała dla tabeli " "symboli\n" -#: src/elflint.c:1976 +#: src/elflint.c:1980 #, c-format msgid "" "section [%2d] '%s': extended section index in section [%2zu] '%s' refers to " @@ -2253,24 +2260,24 @@ msgstr "" "sekcja [%2d] „%s”: rozszerzony indeks sekcji w sekcji [%2zu] „%s” odwołuje " "się do tej samej tabeli symboli\n" -#: src/elflint.c:1994 +#: src/elflint.c:1998 #, c-format msgid "symbol 0 should have zero extended section index\n" msgstr "symbol 0 powinien mieć zerowy rozszerzony indeks sekcji\n" -#: src/elflint.c:2006 +#: src/elflint.c:2010 #, c-format msgid "cannot get data for symbol %zu\n" msgstr "nie można uzyskać danych dla symbolu %zu\n" -#: src/elflint.c:2011 +#: src/elflint.c:2015 #, c-format msgid "extended section index is % but symbol index is not XINDEX\n" msgstr "" "rozszerzony indeks sekcji wynosi %, ale indeks symbolu nie wynosi " "XINDEX\n" -#: src/elflint.c:2028 src/elflint.c:2085 +#: src/elflint.c:2032 src/elflint.c:2089 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n" @@ -2278,43 +2285,43 @@ msgstr "" "sekcja [%2d] „%s”: sekcja tabeli mieszającej jest za mała (%ld, oczekiwano " "%ld)\n" -#: src/elflint.c:2042 src/elflint.c:2099 +#: src/elflint.c:2046 src/elflint.c:2103 #, c-format msgid "section [%2d] '%s': chain array too large\n" msgstr "sekcja [%2d] „%s”: tabela łańcuchowa jest za duża\n" -#: src/elflint.c:2056 src/elflint.c:2113 +#: src/elflint.c:2060 src/elflint.c:2117 #, c-format msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n" msgstr "" "sekcja [%2d] „%s”: odwołanie do kubełka skrótu %zu jest spoza zakresu\n" -#: src/elflint.c:2066 +#: src/elflint.c:2070 #, c-format msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n" msgstr "" "sekcja [%2d] „%s”: odwołanie do łańcucha skrótu %zu jest spoza zakresu\n" -#: src/elflint.c:2123 +#: src/elflint.c:2127 #, c-format msgid "section [%2d] '%s': hash chain reference % out of bounds\n" msgstr "" "sekcja [%2d] „%s”: odwołanie do łańcucha skrótu % jest spoza " "zakresu\n" -#: src/elflint.c:2136 +#: src/elflint.c:2140 #, c-format msgid "section [%2d] '%s': not enough data\n" msgstr "sekcja [%2d] „%s”: brak wystarczającej ilości danych\n" -#: src/elflint.c:2148 +#: src/elflint.c:2152 #, c-format msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n" msgstr "" "sekcja [%2d] „%s”: rozmiar maski bitowej wynosi zero lub nie jest potęgą 2: " "%u\n" -#: src/elflint.c:2164 +#: src/elflint.c:2168 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected at " @@ -2323,13 +2330,13 @@ msgstr "" "sekcja [%2d] „%s”: sekcja tabeli mieszającej jest za mała (wynosi %ld, " "oczekiwano co najmniej %ld)\n" -#: src/elflint.c:2173 +#: src/elflint.c:2177 #, c-format msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n" msgstr "" "sekcja [%2d] „%s”: drugie przesunięcie funkcji mieszającej jest za duże: %u\n" -#: src/elflint.c:2207 +#: src/elflint.c:2211 #, c-format msgid "" "section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n" @@ -2337,7 +2344,7 @@ msgstr "" "sekcja [%2d] „%s”: łańcuch mieszający dla kubełka %zu jest mniejszy niż " "przesunięcie indeksu symboli\n" -#: src/elflint.c:2228 +#: src/elflint.c:2232 #, c-format msgid "" "section [%2d] '%s': symbol %u referenced in chain for bucket %zu is " @@ -2346,7 +2353,7 @@ msgstr "" "sekcja [%2d] „%s”: symbol %u wskazywany w łańcuchu dla kubełka %zu jest " "nieokreślony\n" -#: src/elflint.c:2241 +#: src/elflint.c:2245 #, c-format msgid "" "section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n" @@ -2354,7 +2361,7 @@ msgstr "" "sekcja [%2d] „%s”: wartość skrótu dla symbolu %u w łańcuchu dla kubełka %zu " "jest błędna\n" -#: src/elflint.c:2250 +#: src/elflint.c:2254 #, c-format msgid "" "section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n" @@ -2362,12 +2369,12 @@ msgstr "" "sekcja [%2d] „%s”: indeks maski dla symbolu %u w łańcuchu dla kubełka %zu " "jest błędny\n" -#: src/elflint.c:2280 +#: src/elflint.c:2284 #, c-format msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n" msgstr "sekcja [%2d] „%s”: łańcuch skrótu dla kubełka %zu jest spoza zakresu\n" -#: src/elflint.c:2285 +#: src/elflint.c:2289 #, c-format msgid "" "section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n" @@ -2375,41 +2382,41 @@ msgstr "" "sekcja [%2d] „%s”: odwołanie do symbolu w łańcuchu dla kubełka %zu jest " "spoza zakresu\n" -#: src/elflint.c:2291 +#: src/elflint.c:2295 #, c-format msgid "section [%2d] '%s': bitmask does not match names in the hash table\n" msgstr "" "sekcja [%2d] „%s”: maska bitowa nie pasuje do nazw w tabeli mieszającej\n" -#: src/elflint.c:2304 +#: src/elflint.c:2308 #, c-format msgid "section [%2d] '%s': relocatable files cannot have hash tables\n" msgstr "" "sekcja [%2d] „%s”: pliki relokowalne nie mogą mieć tabeli mieszających\n" -#: src/elflint.c:2322 +#: src/elflint.c:2326 #, c-format msgid "section [%2d] '%s': hash table not for dynamic symbol table\n" msgstr "" "sekcja [%2d] „%s”: tabela mieszająca nie dla tabeli dynamicznych symboli\n" -#: src/elflint.c:2326 +#: src/elflint.c:2330 #, c-format msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n" msgstr "" "sekcja [%2d] „%s”: nieprawidłowy indeks sekcji tabeli symboli sh_link [%2d]\n" -#: src/elflint.c:2336 +#: src/elflint.c:2340 #, c-format msgid "section [%2d] '%s': hash table entry size incorrect\n" msgstr "sekcja [%2d] „%s”: niepoprawny rozmiar wpisu tabeli mieszającej\n" -#: src/elflint.c:2341 +#: src/elflint.c:2345 #, c-format msgid "section [%2d] '%s': not marked to be allocated\n" msgstr "sekcja [%2d] „%s”: nieoznaczona do przydzielenia\n" -#: src/elflint.c:2346 +#: src/elflint.c:2350 #, c-format msgid "" "section [%2d] '%s': hash table has not even room for initial administrative " @@ -2418,29 +2425,29 @@ msgstr "" "sekcja [%2d] „%s”: tabela mieszająca nie ma miejsca nawet na początkowe " "wpisy administracyjne\n" -#: src/elflint.c:2395 +#: src/elflint.c:2399 #, c-format msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n" msgstr "" "sh_link w sekcjach skrótu [%2zu] „%s” i [%2zu] „%s” nie są identyczne\n" -#: src/elflint.c:2419 src/elflint.c:2484 src/elflint.c:2519 +#: src/elflint.c:2423 src/elflint.c:2488 src/elflint.c:2523 #, c-format msgid "hash section [%2zu] '%s' does not contain enough data\n" msgstr "" "sekcja mieszania [%2zu] „%s” nie zawiera wystarczającej ilości danych\n" -#: src/elflint.c:2440 +#: src/elflint.c:2444 #, c-format msgid "hash section [%2zu] '%s' has zero bit mask words\n" msgstr "sekcja mieszania [%2zu] „%s” ma zerowe słowa maski bitów\n" -#: src/elflint.c:2451 src/elflint.c:2495 src/elflint.c:2532 +#: src/elflint.c:2455 src/elflint.c:2499 src/elflint.c:2536 #, c-format msgid "hash section [%2zu] '%s' uses too much data\n" msgstr "sekcja mieszania [%2zu] „%s” używa za dużo danych\n" -#: src/elflint.c:2466 +#: src/elflint.c:2470 #, c-format msgid "" "hash section [%2zu] '%s' invalid symbol index % (max_nsyms: " @@ -2449,17 +2456,17 @@ msgstr "" "sekcja mieszająca [%2zu] „%s” nieprawidłowy indeks symboli % " "(max_nsyms: %, nentries: %\n" -#: src/elflint.c:2553 +#: src/elflint.c:2557 #, c-format msgid "hash section [%2zu] '%s' invalid sh_entsize\n" msgstr "sekcja mieszania [%2zu] „%s” nieprawidłowe sh_entsize\n" -#: src/elflint.c:2563 src/elflint.c:2567 +#: src/elflint.c:2567 src/elflint.c:2571 #, c-format msgid "section [%2zu] '%s': reference to symbol index 0\n" msgstr "sekcja [%2zu] „%s”: odwołanie do symbolu o indeksie 0\n" -#: src/elflint.c:2574 +#: src/elflint.c:2578 #, c-format msgid "" "symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash " @@ -2468,7 +2475,7 @@ msgstr "" "symbol %d wymieniony w nowej tabeli mieszającej w [%2zu] „%s”, ale nie " "w poprzedniej tabeli mieszającej [%2zu] „%s”\n" -#: src/elflint.c:2586 +#: src/elflint.c:2590 #, c-format msgid "" "symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash " @@ -2477,12 +2484,12 @@ msgstr "" "symbol %d wymieniony w poprzedniej tabeli mieszającej w [%2zu] „%s”, ale nie " "w nowej tabeli mieszającej w [%2zu] „%s”\n" -#: src/elflint.c:2602 +#: src/elflint.c:2606 #, c-format msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n" msgstr "sekcja [%2d] „%s”: niezerowe sh_%s dla sekcji NULL\n" -#: src/elflint.c:2622 +#: src/elflint.c:2626 #, c-format msgid "" "section [%2d] '%s': section groups only allowed in relocatable object files\n" @@ -2490,96 +2497,96 @@ msgstr "" "sekcja [%2d] „%s”: w plikach obiektów relokowalnych dozwolone są tylko grupy " "sekcji\n" -#: src/elflint.c:2633 +#: src/elflint.c:2637 #, c-format msgid "section [%2d] '%s': cannot get symbol table: %s\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać tabeli symboli: %s\n" -#: src/elflint.c:2638 +#: src/elflint.c:2642 #, c-format msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n" msgstr "" "sekcja [%2d] „%s”: odwołanie do sekcji w sh_link nie ma tabeli symboli\n" -#: src/elflint.c:2644 +#: src/elflint.c:2648 #, c-format msgid "section [%2d] '%s': invalid symbol index in sh_info\n" msgstr "sekcja [%2d] „%s”: nieprawidłowy indeks symbolu w sh_info\n" -#: src/elflint.c:2649 +#: src/elflint.c:2653 #, c-format msgid "section [%2d] '%s': sh_flags not zero\n" msgstr "sekcja [%2d] „%s”: niezerowe sh_flags\n" -#: src/elflint.c:2656 +#: src/elflint.c:2660 #, c-format msgid "section [%2d] '%s': cannot get symbol for signature\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać symbolu dla podpisu\n" -#: src/elflint.c:2660 +#: src/elflint.c:2664 #, c-format msgid "section [%2d] '%s': cannot get symbol name for signature\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać nazwy symbolu dla podpisu\n" -#: src/elflint.c:2665 +#: src/elflint.c:2669 #, c-format msgid "section [%2d] '%s': signature symbol cannot be empty string\n" msgstr "sekcja [%2d] „%s”: symbol podpisu nie można być pustym ciągiem\n" -#: src/elflint.c:2671 +#: src/elflint.c:2675 #, c-format msgid "section [%2d] '%s': sh_flags not set correctly\n" msgstr "sekcja [%2d] „%s”: sh_flags nie ustawione poprawnie\n" -#: src/elflint.c:2677 +#: src/elflint.c:2681 #, c-format msgid "section [%2d] '%s': cannot get data: %s\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać danych: %s\n" -#: src/elflint.c:2686 +#: src/elflint.c:2690 #, c-format msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n" msgstr "" "sekcja [%2d] „%s”: rozmiar sekcji nie jest wielokrotnością " "sizeof(Elf32_Word)\n" -#: src/elflint.c:2692 +#: src/elflint.c:2696 #, c-format msgid "section [%2d] '%s': section group without flags word\n" msgstr "sekcja [%2d] „%s”: grupa sekcji bez słowa flag\n" -#: src/elflint.c:2700 +#: src/elflint.c:2704 #, c-format msgid "section [%2d] '%s': section group without member\n" msgstr "sekcja [%2d] „%s”: grupa sekcji bez elementów\n" -#: src/elflint.c:2704 +#: src/elflint.c:2708 #, c-format msgid "section [%2d] '%s': section group with only one member\n" msgstr "sekcja [%2d] „%s”: grupa sekcji z tylko jednym elementem\n" -#: src/elflint.c:2715 +#: src/elflint.c:2719 #, c-format msgid "section [%2d] '%s': unknown section group flags\n" msgstr "sekcja [%2d] „%s”: nieznane flagi grupy sekcji\n" -#: src/elflint.c:2727 +#: src/elflint.c:2731 #, c-format msgid "section [%2d] '%s': section index %zu out of range\n" msgstr "sekcja [%2d] „%s”: indeks sekcji %zu jest spoza zakresu\n" -#: src/elflint.c:2736 +#: src/elflint.c:2740 #, c-format msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n" msgstr "" "sekcja [%2d] „%s”: nie można uzyskać nagłówka sekcji dla elementu %zu: %s\n" -#: src/elflint.c:2743 +#: src/elflint.c:2747 #, c-format msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n" msgstr "sekcja [%2d] „%s”: grupa sekcji zawiera inną grupę [%2d] „%s”\n" -#: src/elflint.c:2749 +#: src/elflint.c:2753 #, c-format msgid "" "section [%2d] '%s': element %zu references section [%2d] '%s' without " @@ -2588,12 +2595,12 @@ msgstr "" "sekcja [%2d] „%s”: element %zu odwołuje się do sekcji [%2d] „%s” bez flagi " "SHF_GROUP\n" -#: src/elflint.c:2756 +#: src/elflint.c:2760 #, c-format msgid "section [%2d] '%s' is contained in more than one section group\n" msgstr "sekcja [%2d] „%s” jest zawarta w więcej niż jednej grupie sekcji\n" -#: src/elflint.c:2946 +#: src/elflint.c:2950 #, c-format msgid "" "section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no " @@ -2602,7 +2609,7 @@ msgstr "" "sekcja [%2d] „%s” odwołuje się w sh_link do sekcji [%2d] „%s”, która nie " "jest tabelą symboli dynamicznych\n" -#: src/elflint.c:2958 +#: src/elflint.c:2962 #, c-format msgid "" "section [%2d] '%s' has different number of entries than symbol table [%2d] " @@ -2610,76 +2617,76 @@ msgid "" msgstr "" "sekcja [%2d] „%s” ma inną liczbę wpisów niż tabela symboli [%2d] „%s”\n" -#: src/elflint.c:2974 +#: src/elflint.c:2978 #, c-format msgid "section [%2d] '%s': symbol %d: cannot read version data\n" msgstr "sekcja [%2d] „%s”: symbol %d: nie można odczytać danych wersji\n" -#: src/elflint.c:2990 +#: src/elflint.c:2994 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n" msgstr "sekcja [%2d] „%s”: symbol %d: symbol lokalny z zakresem globalnym\n" -#: src/elflint.c:2998 +#: src/elflint.c:3002 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with version\n" msgstr "sekcja [%2d] „%s”: symbol %d: symbol lokalny z wersją\n" -#: src/elflint.c:3012 +#: src/elflint.c:3016 #, c-format msgid "section [%2d] '%s': symbol %d: invalid version index %d\n" msgstr "sekcja [%2d] „%s”: symbol %d: nieprawidłowy indeks wersji %d\n" -#: src/elflint.c:3017 +#: src/elflint.c:3021 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for defined version\n" msgstr "" "sekcja [%2d] „%s”: symbol %d: indeks wersji %d jest dla wersji określonej\n" -#: src/elflint.c:3027 +#: src/elflint.c:3031 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for requested version\n" msgstr "" "sekcja [%2d] „%s”: symbol %d: indeks wersji %d jest dla wersji żądanej\n" -#: src/elflint.c:3080 +#: src/elflint.c:3084 #, c-format msgid "more than one version reference section present\n" msgstr "obecna jest więcej niż jedna sekcja odniesienia wersji\n" -#: src/elflint.c:3088 src/elflint.c:3235 +#: src/elflint.c:3092 src/elflint.c:3239 #, c-format msgid "section [%2d] '%s': sh_link does not link to string table\n" msgstr "sekcja [%2d] „%s”: sh_link nie łączy się z tabelą ciągów\n" -#: src/elflint.c:3113 src/elflint.c:3289 +#: src/elflint.c:3117 src/elflint.c:3293 #, c-format msgid "section [%2d] '%s': entry %d has wrong version %d\n" msgstr "sekcja [%2d] „%s”: wpis %d ma błędną wersję %d\n" -#: src/elflint.c:3120 src/elflint.c:3296 +#: src/elflint.c:3124 src/elflint.c:3300 #, c-format msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n" msgstr "sekcja [%2d] „%s”: wpis %d ma błędny offset dla danych dodatkowych\n" -#: src/elflint.c:3130 +#: src/elflint.c:3134 #, c-format msgid "section [%2d] '%s': entry %d has invalid file reference\n" msgstr "sekcja [%2d] „%s”: symbol %d ma błędne odniesienie do pliku\n" -#: src/elflint.c:3138 +#: src/elflint.c:3142 #, c-format msgid "section [%2d] '%s': entry %d references unknown dependency\n" msgstr "sekcja [%2d] „%s”: wpis %d odnosi się do nieznanej zależności\n" -#: src/elflint.c:3150 +#: src/elflint.c:3154 #, c-format msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n" msgstr "sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma nieznaną flagę\n" -#: src/elflint.c:3158 +#: src/elflint.c:3162 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has invalid name " @@ -2688,7 +2695,7 @@ msgstr "" "sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma nieprawidłowe " "odniesienie do nazwy\n" -#: src/elflint.c:3167 +#: src/elflint.c:3171 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: " @@ -2697,7 +2704,7 @@ msgstr "" "sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma błędną wartość skrótu: " "%#x, oczekiwano %#x\n" -#: src/elflint.c:3176 +#: src/elflint.c:3180 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version " @@ -2706,19 +2713,19 @@ msgstr "" "sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma powtórzoną nazwę wersji " "„%s”\n" -#: src/elflint.c:3187 +#: src/elflint.c:3191 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n" msgstr "" "sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma błędne następne pole\n" -#: src/elflint.c:3204 src/elflint.c:3380 +#: src/elflint.c:3208 src/elflint.c:3384 #, c-format msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n" msgstr "sekcja [%2d] „%s”: wpis %d ma błędny offset do następnego wpisu\n" -#: src/elflint.c:3212 src/elflint.c:3388 +#: src/elflint.c:3216 src/elflint.c:3392 #, c-format msgid "" "section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says " @@ -2727,43 +2734,43 @@ msgstr "" "sekcja [%2d] „%s”: wpis %d ma zerowy offset do następnego wpisu, ale sh_info " "zawiera informacje o większej liczbie wpisów\n" -#: src/elflint.c:3227 +#: src/elflint.c:3231 #, c-format msgid "more than one version definition section present\n" msgstr "obecna jest więcej niż jedna sekcja definicji wersji\n" -#: src/elflint.c:3274 +#: src/elflint.c:3278 #, c-format msgid "section [%2d] '%s': more than one BASE definition\n" msgstr "sekcja [%2d] „%s”: jest więcej niż jedna definicja BASE\n" -#: src/elflint.c:3278 +#: src/elflint.c:3282 #, c-format msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n" msgstr "sekcja [%2d] „%s”: definicja BASE musi mieć indeks VER_NDX_GLOBAL\n" -#: src/elflint.c:3284 +#: src/elflint.c:3288 #, c-format msgid "section [%2d] '%s': entry %d has unknown flag\n" msgstr "sekcja [%2d] „%s”: wpis %d ma nieznaną flagę\n" -#: src/elflint.c:3311 +#: src/elflint.c:3315 #, c-format msgid "section [%2d] '%s': entry %d has invalid name reference\n" msgstr "sekcja [%2d] „%s”: wpis %d ma nieprawidłowe odniesienie do nazwy\n" -#: src/elflint.c:3318 +#: src/elflint.c:3322 #, c-format msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n" msgstr "" "sekcja [%2d] „%s”: wpis %d ma błędną wartość skrótu: %#x, oczekiwano %#x\n" -#: src/elflint.c:3326 +#: src/elflint.c:3330 #, c-format msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n" msgstr "sekcja [%2d] „%s”: wpis %d ma powtórzoną nazwę wersji „%s”\n" -#: src/elflint.c:3346 +#: src/elflint.c:3350 #, c-format msgid "" "section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n" @@ -2771,51 +2778,51 @@ msgstr "" "sekcja [%2d] „%s”: wpis %d ma nieprawidłowe odniesienie do nazwy w danych " "dodatkowych\n" -#: src/elflint.c:3363 +#: src/elflint.c:3367 #, c-format msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n" msgstr "" "sekcja [%2d] „%s”: wpis %d ma błędne następne pole w danych dodatkowych\n" -#: src/elflint.c:3396 +#: src/elflint.c:3400 #, c-format msgid "section [%2d] '%s': no BASE definition\n" msgstr "sekcja [%2d] „%s”: brak definicji BASE\n" -#: src/elflint.c:3412 +#: src/elflint.c:3416 #, c-format msgid "section [%2d] '%s': unknown parent version '%s'\n" msgstr "sekcja [%2d] „%s”: nieznana wersja rodzica „%s”\n" -#: src/elflint.c:3425 +#: src/elflint.c:3429 #, c-format msgid "section [%2d] '%s': empty object attributes section\n" msgstr "sekcja [%2d] „%s”: pusta sekcja atrybutów obiektu\n" -#: src/elflint.c:3446 +#: src/elflint.c:3450 #, c-format msgid "section [%2d] '%s': unrecognized attribute format\n" msgstr "sekcja [%2d] „%s”: nierozpoznany format atrybutu\n" -#: src/elflint.c:3462 +#: src/elflint.c:3466 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute section\n" msgstr "" "sekcja [%2d] „%s”: offset %zu: pole o zerowej długości w sekcji atrybutów\n" -#: src/elflint.c:3471 +#: src/elflint.c:3475 #, c-format msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n" msgstr "" "sekcja [%2d] „%s”: offset %zu: nieprawidłowa długość w sekcji atrybutów\n" -#: src/elflint.c:3483 +#: src/elflint.c:3487 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n" msgstr "sekcja [%2d] „%s”: offset %zu: niezakończony ciąg nazwy producenta\n" -#: src/elflint.c:3500 +#: src/elflint.c:3504 #, c-format msgid "" "section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n" @@ -2823,19 +2830,19 @@ msgstr "" "sekcja [%2d] „%s”: offset %zu: niekończące się ULEB128 w znaczniku podsekcji " "atrybutów\n" -#: src/elflint.c:3509 +#: src/elflint.c:3513 #, c-format msgid "section [%2d] '%s': offset %zu: truncated attribute section\n" msgstr "sekcja [%2d] „%s”: offset %zu: skrócona sekcja atrybutów\n" -#: src/elflint.c:3518 +#: src/elflint.c:3522 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute subsection\n" msgstr "" "sekcja [%2d] „%s”: offset %zu: zerowej długości pole w podsekcji atrybutów\n" -#: src/elflint.c:3533 +#: src/elflint.c:3537 #, c-format msgid "" "section [%2d] '%s': offset %zu: invalid length in attribute subsection\n" @@ -2843,7 +2850,7 @@ msgstr "" "sekcja [%2d] „%s”: offset %zu: nieprawidłowa długość w podsekcji atrybutów\n" #. Tag_File -#: src/elflint.c:3544 +#: src/elflint.c:3548 #, c-format msgid "" "section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n" @@ -2851,23 +2858,23 @@ msgstr "" "sekcja [%2d] „%s”: offset %zu: podsekcja atrybutów ma nieoczekiwany znacznik " "%u\n" -#: src/elflint.c:3562 +#: src/elflint.c:3566 #, c-format msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n" msgstr "" "sekcja [%2d] „%s”: offset %zu: niekończące się ULEB128 w znaczniku atrybutu\n" -#: src/elflint.c:3573 +#: src/elflint.c:3577 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n" msgstr "sekcja [%2d] „%s”: offset %zu: niezakończony ciąg w atrybucie\n" -#: src/elflint.c:3586 +#: src/elflint.c:3590 #, c-format msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n" msgstr "sekcja [%2d] „%s”: offset %zu: nierozpoznany znacznik atrybutu %u\n" -#: src/elflint.c:3590 +#: src/elflint.c:3594 #, c-format msgid "" "section [%2d] '%s': offset %zu: unrecognized %s attribute value %\n" @@ -2875,12 +2882,12 @@ msgstr "" "sekcja [%2d] „%s”: offset %zu: atrybut %s ma nierozpoznaną wartość " "%\n" -#: src/elflint.c:3600 +#: src/elflint.c:3604 #, c-format msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n" msgstr "sekcja [%2d] „%s”: offset %zu: producent „%s” jest nieznany\n" -#: src/elflint.c:3606 +#: src/elflint.c:3610 #, c-format msgid "" "section [%2d] '%s': offset %zu: extra bytes after last attribute section\n" @@ -2888,47 +2895,47 @@ msgstr "" "sekcja [%2d] „%s”: offset %zu: dodatkowe bajty po ostatniej sekcji " "atrybutów\n" -#: src/elflint.c:3695 +#: src/elflint.c:3699 #, c-format msgid "cannot get section header of zeroth section\n" msgstr "nie można uzyskać nagłówka sekcji zerowej\n" -#: src/elflint.c:3699 +#: src/elflint.c:3703 #, c-format msgid "zeroth section has nonzero name\n" msgstr "sekcja zerowa ma niezerową nazwę\n" -#: src/elflint.c:3701 +#: src/elflint.c:3705 #, c-format msgid "zeroth section has nonzero type\n" msgstr "sekcja zerowa ma niezerowy typ\n" -#: src/elflint.c:3703 +#: src/elflint.c:3707 #, c-format msgid "zeroth section has nonzero flags\n" msgstr "sekcja zerowa ma niezerowe flagi\n" -#: src/elflint.c:3705 +#: src/elflint.c:3709 #, c-format msgid "zeroth section has nonzero address\n" msgstr "sekcja zerowa ma niezerowy adres\n" -#: src/elflint.c:3707 +#: src/elflint.c:3711 #, c-format msgid "zeroth section has nonzero offset\n" msgstr "sekcja zerowa ma niezerowy offset\n" -#: src/elflint.c:3709 +#: src/elflint.c:3713 #, c-format msgid "zeroth section has nonzero align value\n" msgstr "sekcja zerowa ma niezerową wartość wyrównania\n" -#: src/elflint.c:3711 +#: src/elflint.c:3715 #, c-format msgid "zeroth section has nonzero entry size value\n" msgstr "sekcja zerowa ma niezerową wartość rozmiaru wpisu\n" -#: src/elflint.c:3714 +#: src/elflint.c:3718 #, c-format msgid "" "zeroth section has nonzero size value while ELF header has nonzero shnum " @@ -2937,7 +2944,7 @@ msgstr "" "sekcja zerowa ma niezerową wartość rozmiaru, a nagłówek ELF ma niezerową " "wartość shnum\n" -#: src/elflint.c:3718 +#: src/elflint.c:3722 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " @@ -2946,7 +2953,7 @@ msgstr "" "sekcja zerowa ma niezerową wartość dowiązań, a nagłówek ELF nie wskazuje " "przepełnienia w shstrndx\n" -#: src/elflint.c:3722 +#: src/elflint.c:3726 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " @@ -2955,46 +2962,46 @@ msgstr "" "sekcja zerowa ma niezerową wartość dowiązań, a nagłówek ELF nie wskazuje " "przepełnienia w phnum\n" -#: src/elflint.c:3740 +#: src/elflint.c:3744 #, c-format msgid "cannot get section header for section [%2zu] '%s': %s\n" msgstr "nie można uzyskać nagłówka sekcji dla sekcji [%2zu] „%s”: %s\n" -#: src/elflint.c:3749 +#: src/elflint.c:3753 #, c-format msgid "section [%2zu]: invalid name\n" msgstr "sekcja [%2zu]: nieprawidłowa nazwa\n" -#: src/elflint.c:3776 +#: src/elflint.c:3780 #, c-format msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n" msgstr "sekcja [%2d] „%s” ma błędny typ: oczekiwano %s, jest %s\n" -#: src/elflint.c:3794 +#: src/elflint.c:3798 #, c-format msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n" msgstr "sekcja [%2zu] „%s” ma błędne flagi: oczekiwano %s, jest %s\n" -#: src/elflint.c:3812 +#: src/elflint.c:3816 #, c-format msgid "" "section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n" msgstr "" "sekcja [%2zu] „%s” ma błędne flagi: oczekiwano %s i być może %s, jest %s\n" -#: src/elflint.c:3830 +#: src/elflint.c:3834 #, c-format msgid "section [%2zu] '%s' present in object file\n" msgstr "sekcja [%2zu] „%s” jest obecna w pliku obiektu\n" -#: src/elflint.c:3836 src/elflint.c:3868 +#: src/elflint.c:3840 src/elflint.c:3872 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n" msgstr "" "sekcja [%2zu] „%s” ma flagę SHF_ALLOC, ale nie ma segmentu wczytywalnego\n" -#: src/elflint.c:3841 src/elflint.c:3873 +#: src/elflint.c:3845 src/elflint.c:3877 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable " @@ -3002,7 +3009,7 @@ msgid "" msgstr "" "sekcja [%2zu] „%s” nie ma flagi SHF_ALLOC, ale są segmenty wczytywalne\n" -#: src/elflint.c:3849 +#: src/elflint.c:3853 #, c-format msgid "" "section [%2zu] '%s' is extension section index table in non-object file\n" @@ -3010,22 +3017,22 @@ msgstr "" "sekcja [%2zu] „%s” jest tabelą indeksów sekcji rozszerzeń w pliku " "nieobiektowym\n" -#: src/elflint.c:3892 +#: src/elflint.c:3896 #, c-format msgid "section [%2zu] '%s': size not multiple of entry size\n" msgstr "sekcja [%2zu] „%s”: rozmiar nie jest wielokrotnością rozmiaru wpisu\n" -#: src/elflint.c:3897 +#: src/elflint.c:3901 #, c-format msgid "cannot get section header\n" msgstr "nie można uzyskać nagłówka sekcji\n" -#: src/elflint.c:3907 +#: src/elflint.c:3911 #, c-format msgid "section [%2zu] '%s' has unsupported type %d\n" msgstr "sekcja [%2zu] „%s” ma nieobsługiwany typ %d\n" -#: src/elflint.c:3922 +#: src/elflint.c:3926 #, c-format msgid "" "section [%2zu] '%s' contains invalid processor-specific flag(s) %#\n" @@ -3033,74 +3040,74 @@ msgstr "" "sekcja [%2zu] „%s” zawiera nieprawidłowe flagi dla konkretnego procesora " "%#\n" -#: src/elflint.c:3929 +#: src/elflint.c:3933 #, c-format msgid "section [%2zu] '%s' contains unknown flag(s) %#\n" msgstr "sekcja [%2zu] „%s” zawiera nieznane flagi %#\n" -#: src/elflint.c:3937 +#: src/elflint.c:3941 #, c-format msgid "section [%2zu] '%s': thread-local data sections address not zero\n" msgstr "" "sekcja [%2zu] „%s”: adres sekcji danych lokalnych dla wątków nie jest zerem\n" -#: src/elflint.c:3947 +#: src/elflint.c:3951 #, c-format msgid "section [%2zu] '%s': allocated section cannot be compressed\n" msgstr "sekcja [%2zu] „%s”: nie można skompresować przydzielonej sekcji\n" -#: src/elflint.c:3952 +#: src/elflint.c:3956 #, c-format msgid "section [%2zu] '%s': nobits section cannot be compressed\n" msgstr "sekcja [%2zu] „%s”: nie można skompresować sekcji „nobits”\n" -#: src/elflint.c:3958 +#: src/elflint.c:3962 #, c-format msgid "" "section [%2zu] '%s': compressed section with no compression header: %s\n" msgstr "sekcja [%2zu] „%s”: skompresowana sekcja bez nagłówka kompresji: %s\n" -#: src/elflint.c:3964 +#: src/elflint.c:3968 #, c-format msgid "section [%2zu] '%s': invalid section reference in link value\n" msgstr "" "sekcja [%2zu] „%s”: nieprawidłowe odwołanie do sekcji w wartości dowiązania\n" -#: src/elflint.c:3969 +#: src/elflint.c:3973 #, c-format msgid "section [%2zu] '%s': invalid section reference in info value\n" msgstr "" "sekcja [%2zu] „%s”: nieprawidłowe odwołanie do sekcji w wartości " "informacyjnej\n" -#: src/elflint.c:3976 +#: src/elflint.c:3980 #, c-format msgid "section [%2zu] '%s': strings flag set without merge flag\n" msgstr "sekcja [%2zu] „%s”: flaga ciągów jest ustawiona bez flagi merge\n" -#: src/elflint.c:3981 +#: src/elflint.c:3985 #, c-format msgid "section [%2zu] '%s': merge flag set but entry size is zero\n" msgstr "" "sekcja [%2zu] „%s”: flaga merge jest ustawiona, ale rozmiar wpisu jest " "zerowy\n" -#: src/elflint.c:4000 +#: src/elflint.c:4004 #, c-format msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n" msgstr "sekcja [%2zu] „%s” ma nieoczekiwany typ %d dla sekcji wykonywalnej\n" -#: src/elflint.c:4009 +#: src/elflint.c:4013 #, c-format msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n" msgstr "sekcja [%2zu] „%s” musi być typu NOBITS w plikach debuginfo\n" -#: src/elflint.c:4016 +#: src/elflint.c:4020 #, c-format msgid "section [%2zu] '%s' is both executable and writable\n" msgstr "sekcja [%2zu] „%s” jest wykonywalne i zapisywalne\n" -#: src/elflint.c:4047 +#: src/elflint.c:4051 #, c-format msgid "" "section [%2zu] '%s' not fully contained in segment of program header entry " @@ -3109,7 +3116,7 @@ msgstr "" "sekcja [%2zu] „%s” nie jest w całości zawarta w segmencie wpisu %d nagłówka " "programu\n" -#: src/elflint.c:4057 +#: src/elflint.c:4061 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " @@ -3118,7 +3125,7 @@ msgstr "" "sekcja [%2zu] „%s” ma typ NOBITS, a jest odczytywana z pliku w segmencie " "wpisu %d nagłówka programu\n" -#: src/elflint.c:4083 +#: src/elflint.c:4087 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " @@ -3127,7 +3134,7 @@ msgstr "" "sekcja [%2zu] „%s” ma typ NOBITS, ale jest odczytywana z pliku w segmencie " "wpisu %d nagłówka programu, a zawartość pliku jest niezerowa\n" -#: src/elflint.c:4094 +#: src/elflint.c:4098 #, c-format msgid "" "section [%2zu] '%s' has not type NOBITS but is not read from the file in " @@ -3136,17 +3143,17 @@ msgstr "" "sekcja [%2zu] „%s” nie ma typu NOBITS, a nie jest odczytywana z pliku " "w segmencie wpisu %d nagłówka programu\n" -#: src/elflint.c:4105 +#: src/elflint.c:4109 #, c-format msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n" msgstr "sekcja [%2zu] „%s” jest wykonywalne w segmencie niewykonywalnym %d\n" -#: src/elflint.c:4115 +#: src/elflint.c:4119 #, c-format msgid "section [%2zu] '%s' is writable in unwritable segment %d\n" msgstr "sekcja [%2zu] „%s” jest zapisywalne w niezapisywalnym segmencie %d\n" -#: src/elflint.c:4125 +#: src/elflint.c:4129 #, c-format msgid "" "section [%2zu] '%s': alloc flag set but section not in any loaded segment\n" @@ -3154,7 +3161,7 @@ msgstr "" "sekcja [%2zu] „%s”: ma flagę alloc, ale sekcja nie jest w żadnym segmencie " "wczytywalnym\n" -#: src/elflint.c:4131 +#: src/elflint.c:4135 #, c-format msgid "" "section [%2zu] '%s': ELF header says this is the section header string table " @@ -3163,7 +3170,7 @@ msgstr "" "sekcja [%2zu] „%s”: według nagłówka ELF to jest tabela ciągów nagłówków " "sekcji, ale typ nie jest SHT_TYPE\n" -#: src/elflint.c:4139 +#: src/elflint.c:4143 #, c-format msgid "" "section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n" @@ -3171,17 +3178,17 @@ msgstr "" "sekcja [%2zu] „%s”: pliki relokowalne nie mogą mieć tabeli symboli " "dynamicznych\n" -#: src/elflint.c:4190 +#: src/elflint.c:4194 #, c-format msgid "more than one version symbol table present\n" msgstr "obecna jest więcej niż jedna tabela symboli wersji\n" -#: src/elflint.c:4213 +#: src/elflint.c:4217 #, c-format msgid "INTERP program header entry but no .interp section\n" msgstr "jest wpis nagłówka programu INTERP, ale nie ma sekcji .interp\n" -#: src/elflint.c:4224 +#: src/elflint.c:4228 #, c-format msgid "" "loadable segment [%u] is executable but contains no executable sections\n" @@ -3189,14 +3196,14 @@ msgstr "" "wczytywalny segment [%u] jest wykonywalny, ale nie zawiera wykonywalnych " "sekcji\n" -#: src/elflint.c:4230 +#: src/elflint.c:4234 #, c-format msgid "loadable segment [%u] is writable but contains no writable sections\n" msgstr "" "wczytywalny segment [%u] jest zapisywalny, ale nie zawiera zapisywalnych " "sekcji\n" -#: src/elflint.c:4241 +#: src/elflint.c:4245 #, c-format msgid "" "no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section " @@ -3205,23 +3212,23 @@ msgstr "" "brak sekcji .gnu.versym, ale istnieje sekcja .gnu.versym_d lub .gnu." "versym_r\n" -#: src/elflint.c:4254 +#: src/elflint.c:4258 #, c-format msgid "duplicate version index %d\n" msgstr "powtórzony indeks wersji %d\n" -#: src/elflint.c:4268 +#: src/elflint.c:4272 #, c-format msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n" msgstr "sekcja .gnu.versym istnieje bez .gnu.versym_d lub .gnu.versym_r\n" -#: src/elflint.c:4317 +#: src/elflint.c:4321 #, c-format msgid "phdr[%d]: unknown core file note type % at offset %\n" msgstr "" "phdr[%d]: nieznany typ notatki pliku core % pod offsetem %\n" -#: src/elflint.c:4321 +#: src/elflint.c:4325 #, c-format msgid "" "section [%2d] '%s': unknown core file note type % at offset %zu\n" @@ -3229,7 +3236,7 @@ msgstr "" "sekcja [%2d]: „%s”: nieznany typ notatki pliku core % pod offsetem " "%zu\n" -#: src/elflint.c:4370 +#: src/elflint.c:4374 #, fuzzy, c-format msgid "" "phdr[%d]: unknown object file note type % with owner name '%s' at " @@ -3237,7 +3244,7 @@ msgid "" msgstr "" "phdr[%d]: nieznany typ notatki pliku obiektu % pod offsetem %zu\n" -#: src/elflint.c:4375 +#: src/elflint.c:4379 #, fuzzy, c-format msgid "" "section [%2d] '%s': unknown object file note type % with owner name " @@ -3246,37 +3253,37 @@ msgstr "" "sekcja [%2d] „%s”: nieznany typ notatki pliku obiektu % pod offsetem " "%zu\n" -#: src/elflint.c:4394 +#: src/elflint.c:4398 #, c-format msgid "phdr[%d]: no note entries defined for the type of file\n" msgstr "phdr[%d]: brak określonych wpisów notatek dla typu pliku\n" -#: src/elflint.c:4414 +#: src/elflint.c:4418 #, c-format msgid "phdr[%d]: cannot get content of note section: %s\n" msgstr "phdr[%d]: nie można uzyskać zawartości sekcji notatki: %s\n" -#: src/elflint.c:4417 +#: src/elflint.c:4421 #, c-format msgid "phdr[%d]: extra % bytes after last note\n" msgstr "phdr[%d]: dodatkowe % bajtów po ostatniej notatce\n" -#: src/elflint.c:4438 +#: src/elflint.c:4442 #, c-format msgid "section [%2d] '%s': no note entries defined for the type of file\n" msgstr "sekcja [%2d] „%s”: brak określonych wpisów notatek dla typu pliku\n" -#: src/elflint.c:4445 +#: src/elflint.c:4449 #, c-format msgid "section [%2d] '%s': cannot get content of note section\n" msgstr "sekcja [%2d] „%s”: nie można uzyskać zawartości sekcji notatek\n" -#: src/elflint.c:4448 +#: src/elflint.c:4452 #, c-format msgid "section [%2d] '%s': extra % bytes after last note\n" msgstr "sekcja [%2d] „%s”: dodatkowe % bajtów po ostatniej notatce\n" -#: src/elflint.c:4466 +#: src/elflint.c:4470 #, c-format msgid "" "only executables, shared objects, and core files can have program headers\n" @@ -3284,135 +3291,135 @@ msgstr "" "tylko pliki wykonywalne, obiekty współdzielone i pliki core mogą mieć " "nagłówki programu\n" -#: src/elflint.c:4481 +#: src/elflint.c:4485 #, c-format msgid "cannot get program header entry %d: %s\n" msgstr "nie można uzyskać wpisu nagłówka programu %d: %s\n" -#: src/elflint.c:4490 +#: src/elflint.c:4499 #, c-format msgid "program header entry %d: unknown program header entry type %#\n" msgstr "" "wpis nagłówka programu %d: nieznany typ wpisu nagłówka programu %#\n" -#: src/elflint.c:4501 +#: src/elflint.c:4510 #, c-format msgid "more than one INTERP entry in program header\n" msgstr "więcej niż jeden wpis INTERP w nagłówku programu\n" -#: src/elflint.c:4509 +#: src/elflint.c:4518 #, c-format msgid "more than one TLS entry in program header\n" msgstr "więcej niż jeden wpis TLS w nagłówku programu\n" -#: src/elflint.c:4516 +#: src/elflint.c:4525 #, c-format msgid "static executable cannot have dynamic sections\n" msgstr "statyczny plik wykonywalny nie może mieć sekcji dynamicznych\n" -#: src/elflint.c:4530 +#: src/elflint.c:4539 #, c-format msgid "dynamic section reference in program header has wrong offset\n" msgstr "odniesienie sekcji dynamicznej w nagłówku programu ma błędny offset\n" -#: src/elflint.c:4533 +#: src/elflint.c:4542 #, c-format msgid "dynamic section size mismatch in program and section header\n" msgstr "różne rozmiary sekcji dynamicznej w nagłówku programu i sekcji\n" -#: src/elflint.c:4543 +#: src/elflint.c:4552 #, c-format msgid "more than one GNU_RELRO entry in program header\n" msgstr "więcej niż jeden wpis GNU_RELRO w nagłówku programu\n" -#: src/elflint.c:4564 +#: src/elflint.c:4573 #, c-format msgid "loadable segment GNU_RELRO applies to is not writable\n" msgstr "wczytywalny segment wskazywany przez GNU_RELRO nie jest zapisywalny\n" -#: src/elflint.c:4575 +#: src/elflint.c:4584 #, c-format msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n" msgstr "flagi wczytywalnego segmentu [%u] nie pasują do flag GNU_RELRO [%u]\n" -#: src/elflint.c:4582 +#: src/elflint.c:4591 #, c-format msgid "" "GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n" msgstr "" "flagi GNU_RELRO [%u] nie są podzbiorem flag wczytywalnego segmentu [%u]\n" -#: src/elflint.c:4591 src/elflint.c:4614 +#: src/elflint.c:4600 src/elflint.c:4623 #, c-format msgid "%s segment not contained in a loaded segment\n" msgstr "segment %s nie zawiera się we wczytywalnym segmencie\n" -#: src/elflint.c:4620 +#: src/elflint.c:4629 #, c-format msgid "program header offset in ELF header and PHDR entry do not match" msgstr "" "offsety nagłówka programu w nagłówku ELF i wpisie PHDR nie zgadzają się" -#: src/elflint.c:4647 +#: src/elflint.c:4656 #, c-format msgid "call frame search table reference in program header has wrong offset\n" msgstr "" "odniesienie tabeli wyszukiwania ramki wywołania w nagłówku programu ma " "błędny offset\n" -#: src/elflint.c:4650 +#: src/elflint.c:4659 #, c-format msgid "call frame search table size mismatch in program and section header\n" msgstr "" "różne rozmiary tabel wyszukiwania ramki wywołania w nagłówku programu " "i sekcji\n" -#: src/elflint.c:4663 +#: src/elflint.c:4672 #, c-format msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n" msgstr "PT_GNU_EH_FRAME jest obecne, ale brak sekcji .eh_frame_hdr\n" -#: src/elflint.c:4671 +#: src/elflint.c:4680 #, c-format msgid "call frame search table must be allocated\n" msgstr "tabela wyszukiwania ramki wywołania musi być przydzielona\n" -#: src/elflint.c:4674 +#: src/elflint.c:4683 #, c-format msgid "section [%2zu] '%s' must be allocated\n" msgstr "sekcja [%2zu] „%s”: musi być przydzielona\n" -#: src/elflint.c:4678 +#: src/elflint.c:4687 #, c-format msgid "call frame search table must not be writable\n" msgstr "tabela wyszukiwania ramki wywołania nie może być zapisywalna\n" -#: src/elflint.c:4681 +#: src/elflint.c:4690 #, c-format msgid "section [%2zu] '%s' must not be writable\n" msgstr "sekcja [%2zu] „%s” nie może być zapisywalna\n" -#: src/elflint.c:4686 +#: src/elflint.c:4695 #, c-format msgid "call frame search table must not be executable\n" msgstr "tabela wyszukiwania ramki wywołania nie może być wykonywalna\n" -#: src/elflint.c:4689 +#: src/elflint.c:4698 #, c-format msgid "section [%2zu] '%s' must not be executable\n" msgstr "sekcja [%2zu] „%s” nie może być wykonywalna\n" -#: src/elflint.c:4700 +#: src/elflint.c:4709 #, c-format msgid "program header entry %d: file size greater than memory size\n" msgstr "wpis nagłówka programu %d: rozmiar pliku większy niż rozmiar pamięci\n" -#: src/elflint.c:4707 +#: src/elflint.c:4716 #, c-format msgid "program header entry %d: alignment not a power of 2\n" msgstr "wpis nagłówka programu %d: wyrównanie nie jest potęgą 2\n" -#: src/elflint.c:4710 +#: src/elflint.c:4719 #, c-format msgid "" "program header entry %d: file offset and virtual address not module of " @@ -3421,7 +3428,7 @@ msgstr "" "wpis nagłówka programu %d: offset w pliku i adres wirtualny nie są " "wielokrotnością wyrównania\n" -#: src/elflint.c:4723 +#: src/elflint.c:4732 #, c-format msgid "" "executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME " @@ -3430,12 +3437,12 @@ msgstr "" "plik wykonywalny/DSO z sekcją .eh_frame_hdr nie ma wpisu nagłówka programu " "PT_GNU_EH_FRAME" -#: src/elflint.c:4757 +#: src/elflint.c:4766 #, c-format msgid "cannot read ELF header: %s\n" msgstr "nie można odczytać nagłówka ELF: %s\n" -#: src/elflint.c:4783 +#: src/elflint.c:4792 #, c-format msgid "text relocation flag set but not needed\n" msgstr "flaga relokacji tekstu jest ustawiona, ale niepotrzebna\n" diff --git a/libdrgn/elfutils/po/uk.po b/libdrgn/elfutils/po/uk.po index 0ca049e72..051cc0bb2 100644 --- a/libdrgn/elfutils/po/uk.po +++ b/libdrgn/elfutils/po/uk.po @@ -2,13 +2,13 @@ # Copyright (C) 2010 Free Software Foundation, Inc. # This file is distributed under the same license as the elfutils package. # -# Yuri Chornoivan , 2010, 2011, 2012, 2013, 2014, 2015. +# Yuri Chornoivan , 2010, 2011, 2012, 2013, 2014, 2015, 2020. msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n" -"POT-Creation-Date: 2019-11-26 09:48+0100\n" -"PO-Revision-Date: 2015-09-26 16:41+0300\n" +"POT-Creation-Date: 2020-03-30 12:56+0200\n" +"PO-Revision-Date: 2020-03-28 14:59+0200\n" "Last-Translator: Yuri Chornoivan \n" "Language-Team: Ukrainian \n" "Language: uk\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" -"X-Generator: Lokalize 1.5\n" +"X-Generator: Lokalize 20.03.70\n" #: lib/color.c:53 msgid "" @@ -47,13 +47,13 @@ msgid "cannot allocate memory" msgstr "не вдалося розподілити пам’ять" #: lib/printversion.c:40 -#, fuzzy, c-format +#, c-format msgid "" "Copyright (C) %s The elfutils developers <%s>.\n" "This is free software; see the source for copying conditions. There is NO\n" "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" msgstr "" -"© Red Hat, Inc., %s\n" +"© Розробники elfutils, %s <%s>.\n" "Це програмне забезпечення є вільним, умови копіювання викладено у його " "початкових кодах. Умовами ліцензування програми НЕ передбачено жодних " "гарантій, зокрема гарантій працездатності або придатності для певної мети.\n" @@ -172,19 +172,16 @@ msgid "no string data" msgstr "немає рядкових даних" #: libdw/dwarf_error.c:75 -#, fuzzy msgid ".debug_str section missing" -msgstr "немає розділу .debug_ranges" +msgstr "пропущено розділ .debug_str" #: libdw/dwarf_error.c:76 -#, fuzzy msgid ".debug_line_str section missing" -msgstr "немає розділу .debug_line" +msgstr "пропущено розділ .debug_line_str" #: libdw/dwarf_error.c:77 -#, fuzzy msgid ".debug_str_offsets section missing" -msgstr "немає розділу .debug_ranges" +msgstr "пропущено розділ .debug_str_offsets" #: libdw/dwarf_error.c:78 msgid "no address value" @@ -227,19 +224,16 @@ msgid "address out of range" msgstr "некоректна адреса" #: libdw/dwarf_error.c:88 -#, fuzzy msgid ".debug_loc section missing" -msgstr "немає розділу .debug_line" +msgstr "пропущено розділ .debug_loc" #: libdw/dwarf_error.c:89 -#, fuzzy msgid ".debug_loclists section missing" -msgstr "немає розділу .debug_line" +msgstr "пропущено розділ .debug_loclists" #: libdw/dwarf_error.c:90 -#, fuzzy msgid "not a location list value" -msgstr "немає значення списку адрес" +msgstr "не є значенням списку адрес" #: libdw/dwarf_error.c:91 msgid "no block data" @@ -270,9 +264,8 @@ msgid ".debug_ranges section missing" msgstr "немає розділу .debug_ranges" #: libdw/dwarf_error.c:98 -#, fuzzy msgid ".debug_rnglists section missing" -msgstr "немає розділу .debug_ranges" +msgstr "пропущено розділ .debug_rnglists" #: libdw/dwarf_error.c:99 msgid "invalid CFI section" @@ -291,14 +284,12 @@ msgid "not a CU (unit) DIE" msgstr "не є DIE CU (модуля)" #: libdw/dwarf_error.c:103 -#, fuzzy msgid "unknown language code" -msgstr " невідомий код операції" +msgstr "невідомий код мови" #: libdw/dwarf_error.c:104 -#, fuzzy msgid ".debug_addr section missing" -msgstr "немає розділу .debug_ranges" +msgstr "пропущено розділ .debug_addr" #: libdwfl/argp-std.c:50 src/stack.c:638 src/unstrip.c:2540 msgid "Input selection options:" @@ -360,9 +351,8 @@ msgid "cannot read ELF core file: %s" msgstr "не вдалося прочитати файл core ELF: %s" #: libdwfl/argp-std.c:320 -#, fuzzy msgid "Not enough memory" -msgstr "нестача пам'яті" +msgstr "Бракує пам'яті" #: libdwfl/argp-std.c:330 msgid "No modules recognized in core file" @@ -527,7 +517,7 @@ msgstr "Немає сервера" #: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:77 #: libebl/eblobjnotetypename.c:109 libebl/eblobjnotetypename.c:130 #: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83 -#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:79 +#: libebl/eblsectiontypename.c:115 libebl/eblsegmenttypename.c:85 msgid "" msgstr "<невідомо>" @@ -631,9 +621,8 @@ msgid "invalid file descriptor" msgstr "некоректний дескриптор файла" #: libelf/elf_error.c:99 -#, fuzzy msgid "invalid ELF file data" -msgstr "некоректний файл ELF" +msgstr "некоректні дані щодо файла ELF" #: libelf/elf_error.c:103 msgid "invalid operation" @@ -753,38 +742,32 @@ msgid "file has no program header" msgstr "у файлі немає заголовка програми" #: libelf/elf_error.c:241 -#, fuzzy msgid "invalid section type" -msgstr "некоректний розділ" +msgstr "некоректний тип розділу" #: libelf/elf_error.c:246 -#, fuzzy msgid "invalid section flags" -msgstr "некоректний розділ" +msgstr "некоректні прапорці розділу" #: libelf/elf_error.c:251 -#, fuzzy msgid "section does not contain compressed data" -msgstr "розділ хешу [%2zu] «%s» містить недостатньо даних\n" +msgstr "розділ не містить стиснутих даних" #: libelf/elf_error.c:256 msgid "section contains compressed data" -msgstr "" +msgstr "розділ містить стиснені дані" #: libelf/elf_error.c:261 -#, fuzzy msgid "unknown compression type" -msgstr "невизначений тип" +msgstr "невідомий тип стиснення" #: libelf/elf_error.c:266 -#, fuzzy msgid "cannot compress data" -msgstr "не вдалося розпакувати DWARF" +msgstr "неможливо стиснути дані" #: libelf/elf_error.c:271 -#, fuzzy msgid "cannot decompress data" -msgstr "не вдалося розпакувати DWARF" +msgstr "неможливо розпакувати дані" #: src/addr2line.c:57 msgid "Input format options:" @@ -1131,29 +1114,29 @@ msgid "cannot read %s: %s" msgstr "не вдалося прочитати %s: %s" #: src/ar.c:1476 -#, fuzzy, c-format +#, c-format msgid "cannot represent ar_date" -msgstr "не вдалося розпакувати DWARF" +msgstr "неможливо представити ar_date" #: src/ar.c:1482 -#, fuzzy, c-format +#, c-format msgid "cannot represent ar_uid" -msgstr "не вдалося розпакувати DWARF" +msgstr "неможливо представити ar_uid" #: src/ar.c:1488 -#, fuzzy, c-format +#, c-format msgid "cannot represent ar_gid" -msgstr "не вдалося розпакувати DWARF" +msgstr "неможливо представити ar_gid" #: src/ar.c:1494 -#, fuzzy, c-format +#, c-format msgid "cannot represent ar_mode" -msgstr "не вдалося отримати назву розділу" +msgstr "неможливо представити ar_mode" #: src/ar.c:1500 -#, fuzzy, c-format +#, c-format msgid "cannot represent ar_size" -msgstr "не вдалося відкрити %s" +msgstr "неможливо представити ar_size" #: src/arlib-argp.c:32 msgid "Use zero for uid, gid, and date in archive members." @@ -1255,14 +1238,14 @@ msgid "%s %s diff: program header count" msgstr "%s %s diff: кількість заголовків програми" #: src/elfcmp.c:241 src/elfcmp.c:244 -#, fuzzy, c-format +#, c-format msgid "cannot get hdrstrndx of '%s': %s" -msgstr "не вдалося отримати заголовок ELF «%s»: %s" +msgstr "не вдалося отримати hdrstrndx «%s»: %s" #: src/elfcmp.c:249 -#, fuzzy, c-format +#, c-format msgid "%s %s diff: shdr string index" -msgstr "%s %s diff: кількість розділів" +msgstr "різниця між %s і %s: індекс рядків shdr" #: src/elfcmp.c:307 #, c-format @@ -1412,31 +1395,29 @@ msgid "-o option specified twice" msgstr "параметр -o вказано двічі" #: src/elfcompress.c:122 -#, fuzzy, c-format +#, c-format msgid "-t option specified twice" -msgstr "параметр -f вказано двічі" +msgstr "параметр -t вказано двічі" #: src/elfcompress.c:131 -#, fuzzy, c-format +#, c-format msgid "unknown compression type '%s'" -msgstr "невизначений тип" +msgstr "невідомий тип стиснення «%s»" #. We need at least one input file. #: src/elfcompress.c:143 src/elfcompress.c:1347 -#, fuzzy, c-format +#, c-format msgid "No input file given" -msgstr "вхідний файл є порожнім" +msgstr "Не надано файла вхідних даних" #: src/elfcompress.c:149 src/elfcompress.c:1352 -#, fuzzy, c-format +#, c-format msgid "Only one input file allowed together with '-o'" -msgstr "" -"Разом з «-o» або «-f» можна використовувати лише один файл вхідних даних" +msgstr "З параметром «-o» можна використовувати лише один файл вхідних даних" #: src/elfcompress.c:1309 -#, fuzzy msgid "Place (de)compressed output into FILE" -msgstr "Вивести дані після вилучення до ФАЙЛа" +msgstr "Помістити результати розпакування або стискання до ФАЙЛа" #: src/elfcompress.c:1312 msgid "" @@ -1444,22 +1425,31 @@ msgid "" "'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias) or 'zlib-" "gnu' (.zdebug GNU style compression, 'gnu' is an alias)" msgstr "" +"Визначає тип стискання, який слід застосувати. ТИПом може бути " +"«none» (розпакувати), «zlib» (стискання ELF ZLIB, типовий варіант, інша " +"назва — «zlib-gabi») або «zlib-gnu» (стискання у стилі GNU .zdebug, інша " +"назва — «gnu»)" #: src/elfcompress.c:1315 msgid "" "SECTION name to (de)compress, SECTION is an extended wildcard pattern " "(defaults to '.?(z)debug*')" msgstr "" +"назва РОЗДІЛу для розпакування або стискання, РОЗДІЛ є розширеним взірцем із " +"замінниками (типове значення -- «.?(z)debug*»)" #: src/elfcompress.c:1318 msgid "Print a message for each section being (de)compressed" msgstr "" +"Вивести повідомлення для кожного розділу, який розпаковується чи стискається" #: src/elfcompress.c:1321 msgid "" "Force compression of section even if it would become larger or update/" "rewrite the file even if no section would be (de)compressed" msgstr "" +"Примусове стискання розділу, навіть якщо він стане більшим, або оновлення чи " +"перезапис файла, навіть якщо жодного розділу не буде розпаковано або стиснено" #: src/elfcompress.c:1324 src/strip.c:93 msgid "Relax a few rules to handle slightly broken ELF files" @@ -1467,10 +1457,8 @@ msgstr "" "Знехтувати декількома правилами для обробки трохи пошкоджених файлів ELF" #: src/elfcompress.c:1327 -#, fuzzy msgid "Be silent when a section cannot be compressed" -msgstr "" -"розділ [%2zu] «%s»: адреса розділів локальних даних потоків не є нульовою\n" +msgstr "Не сповіщати, якщо розділ неможливо стиснути" #. Strings for arguments in help texts. #: src/elfcompress.c:1336 src/elflint.c:77 src/readelf.c:158 @@ -1479,7 +1467,7 @@ msgstr "ФАЙЛ..." #: src/elfcompress.c:1337 msgid "Compress or decompress sections in an ELF file." -msgstr "" +msgstr "Стиснути або розпакувати розділи у файлі ELF." #: src/elflint.c:63 msgid "Be extremely strict, flag level 2 features." @@ -1508,14 +1496,14 @@ msgstr "" "Педантична перевірка файлів ELF на сумісність зі специфікаціями gABI/psABI." #: src/elflint.c:154 src/readelf.c:368 -#, fuzzy, c-format +#, c-format msgid "cannot open input file '%s'" -msgstr "не вдалося відкрити вхідний файл." +msgstr "не вдалося відкрити вхідний файл «%s»" #: src/elflint.c:161 -#, fuzzy, c-format +#, c-format msgid "cannot generate Elf descriptor for '%s': %s\n" -msgstr "не вдалося створити дескриптор Elf: %s\n" +msgstr "не вдалося створити дескриптор Elf для «%s»: %s\n" #: src/elflint.c:180 #, c-format @@ -1562,7 +1550,7 @@ msgid "unsupported OS ABI e_ident[%d] == '%s'\n" msgstr "непідтримуване ABI ОС e_ident[%d] == «%s»\n" #: src/elflint.c:380 -#, fuzzy, c-format +#, c-format msgid "unsupported ABI version e_ident[%d] == %d\n" msgstr "непідтримувана версія ABI e_ident[%d] == %d\n" @@ -1626,7 +1614,7 @@ msgstr "некоректний індекс заголовка розділу\n" #: src/elflint.c:473 #, c-format msgid "Can only check %u headers, shnum was %u\n" -msgstr "" +msgstr "Можна перевірити лише %u заголовків, значенням же shnum було %u\n" #: src/elflint.c:487 #, c-format @@ -1636,7 +1624,7 @@ msgstr "некоректна кількість записів таблиці з #: src/elflint.c:504 #, c-format msgid "Can only check %u headers, phnum was %u\n" -msgstr "" +msgstr "Можна перевірити лише %u заголовків, значенням же phnum було %u\n" #: src/elflint.c:509 #, c-format @@ -1685,14 +1673,14 @@ msgstr "" "розділ [%2d] «%s»: групу розділів [%2zu] «%s» мало бути визначено до розділу-" "елемента цієї групи\n" -#: src/elflint.c:610 src/elflint.c:1494 src/elflint.c:1545 src/elflint.c:1651 -#: src/elflint.c:1987 src/elflint.c:2313 src/elflint.c:2932 src/elflint.c:3095 -#: src/elflint.c:3243 src/elflint.c:3433 src/elflint.c:4431 +#: src/elflint.c:610 src/elflint.c:1498 src/elflint.c:1549 src/elflint.c:1655 +#: src/elflint.c:1991 src/elflint.c:2317 src/elflint.c:2936 src/elflint.c:3099 +#: src/elflint.c:3247 src/elflint.c:3437 src/elflint.c:4435 #, c-format msgid "section [%2d] '%s': cannot get section data\n" msgstr "розділ [%2d] «%s»: не вдалося отримати дані розділу\n" -#: src/elflint.c:623 src/elflint.c:1658 +#: src/elflint.c:623 src/elflint.c:1662 #, c-format msgid "" "section [%2d] '%s': referenced as string table for section [%2d] '%s' but " @@ -1715,33 +1703,42 @@ msgstr "" msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n" msgstr "розділ [%2u] «%s»: розмірність запису не відповідає ElfXX_Sym\n" -#: src/elflint.c:667 +#: src/elflint.c:662 +#, c-format +msgid "" +"section [%2u] '%s': number of local entries in 'st_info' larger than table " +"size\n" +msgstr "" +"розділ [%2u] «%s»: кількість локальних записів у «st_info» перевищує розмір " +"таблиці\n" + +#: src/elflint.c:671 #, c-format msgid "section [%2d] '%s': cannot get symbol %d: %s\n" msgstr "розділ [%2d] «%s»: не вдалося отримати символ %d: %s\n" -#: src/elflint.c:672 src/elflint.c:675 src/elflint.c:678 src/elflint.c:681 -#: src/elflint.c:684 src/elflint.c:687 +#: src/elflint.c:676 src/elflint.c:679 src/elflint.c:682 src/elflint.c:685 +#: src/elflint.c:688 src/elflint.c:691 #, c-format msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n" msgstr "розділ [%2d] «%s»: «%s» у нульовому записі не є нулем\n" -#: src/elflint.c:690 +#: src/elflint.c:694 #, c-format msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n" msgstr "розділ [%2d] «%s»: XINDEX для нульового запису не є нулем\n" -#: src/elflint.c:700 +#: src/elflint.c:704 #, c-format msgid "section [%2d] '%s': cannot get symbol %zu: %s\n" msgstr "розділ [%2d] «%s»: не вдалося отримати символ %zu: %s\n" -#: src/elflint.c:709 +#: src/elflint.c:713 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid name value\n" msgstr "розділ [%2d] «%s»: символ %zu: некоректне значення назви\n" -#: src/elflint.c:724 +#: src/elflint.c:728 #, c-format msgid "" "section [%2d] '%s': symbol %zu: too large section index but no extended " @@ -1750,7 +1747,7 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: занадто великий покажчик розділу за умови, що " "не визначено розділу розширеного покажчика розділів\n" -#: src/elflint.c:730 +#: src/elflint.c:734 #, c-format msgid "" "section [%2d] '%s': symbol %zu: XINDEX used for index which would fit in " @@ -1760,29 +1757,29 @@ msgstr "" "відповідає st_shndx (%)\n" #. || sym->st_shndx > SHN_HIRESERVE always false -#: src/elflint.c:742 +#: src/elflint.c:746 #, c-format msgid "section [%2d] '%s': symbol %zu: invalid section index\n" msgstr "розділ [%2d] «%s»: символ %zu: некоректний індекс розділу\n" -#: src/elflint.c:750 +#: src/elflint.c:754 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown type\n" msgstr "розділ [%2d] «%s»: символ %zu: невідомий тип\n" -#: src/elflint.c:756 +#: src/elflint.c:760 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown symbol binding\n" msgstr "розділ [%2d] «%s»: символ %zu: невідома прив’язка символу\n" -#: src/elflint.c:761 +#: src/elflint.c:765 #, c-format msgid "section [%2d] '%s': symbol %zu: unique symbol not of object type\n" msgstr "" "розділ [%2d] «%s»: символ %zu: унікальний символ, що не належить до типу " "об’єктів\n" -#: src/elflint.c:769 +#: src/elflint.c:773 #, c-format msgid "" "section [%2d] '%s': symbol %zu: COMMON only allowed in relocatable files\n" @@ -1790,14 +1787,14 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: COMMON можна використовувати лише у файлах, " "придатних до пересування\n" -#: src/elflint.c:773 +#: src/elflint.c:777 #, c-format msgid "section [%2d] '%s': symbol %zu: local COMMON symbols are nonsense\n" msgstr "" "розділ [%2d] «%s»: символ %zu: використання локальних символів COMMON " "позбавлене сенсу\n" -#: src/elflint.c:777 +#: src/elflint.c:781 #, c-format msgid "" "section [%2d] '%s': symbol %zu: function in COMMON section is nonsense\n" @@ -1805,13 +1802,13 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: використання функції у розділі COMMON " "позбавлене сенсу\n" -#: src/elflint.c:828 +#: src/elflint.c:832 #, c-format msgid "section [%2d] '%s': symbol %zu: st_value out of bounds\n" msgstr "" "розділ [%2d] «%s»: символ %zu: значення st_value поза можливим діапазоном\n" -#: src/elflint.c:834 src/elflint.c:859 src/elflint.c:908 +#: src/elflint.c:838 src/elflint.c:863 src/elflint.c:912 #, c-format msgid "" "section [%2d] '%s': symbol %zu does not fit completely in referenced section " @@ -1820,7 +1817,7 @@ msgstr "" "розділ [%2d] «%s»: символ %zu не повністю відповідає розділу, на який " "посилається, [%2d] «%s»\n" -#: src/elflint.c:843 +#: src/elflint.c:847 #, c-format msgid "" "section [%2d] '%s': symbol %zu: referenced section [%2d] '%s' does not have " @@ -1829,7 +1826,7 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: для розділу посилання [%2d] «%s» не " "встановлено прапорець SHF_TLS\n" -#: src/elflint.c:853 src/elflint.c:901 +#: src/elflint.c:857 src/elflint.c:905 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value out of bounds of referenced section " @@ -1838,14 +1835,14 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: значення st_value поза межами розділу " "посилання, [%2d] «%s»\n" -#: src/elflint.c:880 +#: src/elflint.c:884 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but no TLS program header entry\n" msgstr "" "розділ [%2d] «%s»: символ %zu: символ TLS без запису заголовка програми TLS\n" -#: src/elflint.c:886 +#: src/elflint.c:890 #, c-format msgid "" "section [%2d] '%s': symbol %zu: TLS symbol but couldn't get TLS program " @@ -1854,7 +1851,7 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: маємо символ TLS, але не вдалося отримати " "запис заголовка програми TLS\n" -#: src/elflint.c:894 +#: src/elflint.c:898 #, c-format msgid "" "section [%2d] '%s': symbol %zu: st_value short of referenced section [%2d] " @@ -1863,7 +1860,7 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: значення st_value перед розділом посилання, " "[%2d] «%s»\n" -#: src/elflint.c:921 +#: src/elflint.c:925 #, c-format msgid "" "section [%2d] '%s': symbol %zu: local symbol outside range described in " @@ -1872,7 +1869,7 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: у sh_info описано локальний символ поза " "діапазоном\n" -#: src/elflint.c:928 +#: src/elflint.c:932 #, c-format msgid "" "section [%2d] '%s': symbol %zu: non-local symbol outside range described in " @@ -1881,12 +1878,12 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: у sh_info описано нелокальний символ поза " "діапазоном\n" -#: src/elflint.c:935 +#: src/elflint.c:939 #, c-format msgid "section [%2d] '%s': symbol %zu: non-local section symbol\n" msgstr "розділ [%2d] «%s»: символ %zu: нелокальний символ розділу\n" -#: src/elflint.c:985 +#: src/elflint.c:989 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section " @@ -1895,7 +1892,7 @@ msgstr "" "розділ [%2d] «%s»: символ _GLOBAL_OFFSET_TABLE_ посилається на помилковий " "розділ, [%2d]\n" -#: src/elflint.c:992 +#: src/elflint.c:996 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] " @@ -1907,7 +1904,7 @@ msgstr "" #. This test is more strict than the psABIs which #. usually allow the symbol to be in the middle of #. the .got section, allowing negative offsets. -#: src/elflint.c:1008 +#: src/elflint.c:1012 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %# does not " @@ -1916,7 +1913,7 @@ msgstr "" "розділ [%2d] «%s»: значення символу _GLOBAL_OFFSET_TABLE_ %# не " "відповідає адресі розділу %s %#\n" -#: src/elflint.c:1015 +#: src/elflint.c:1019 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size % does not " @@ -1925,7 +1922,7 @@ msgstr "" "розділ [%2d] «%s»: розмір символу _GLOBAL_OFFSET_TABLE_ % не " "відповідає розміру розділу %s %\n" -#: src/elflint.c:1023 +#: src/elflint.c:1027 #, c-format msgid "" "section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got " @@ -1934,7 +1931,7 @@ msgstr "" "розділ [%2d] «%s»: виявлено символ _GLOBAL_OFFSET_TABLE_, але не виявлено " "розділу .got\n" -#: src/elflint.c:1039 +#: src/elflint.c:1043 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC_ symbol value %# does not match dynamic " @@ -1943,7 +1940,7 @@ msgstr "" "розділ [%2d] «%s»: значення символу _DYNAMIC_ %# не відповідає " "адресі динамічного сегмента %#\n" -#: src/elflint.c:1046 +#: src/elflint.c:1050 #, c-format msgid "" "section [%2d] '%s': _DYNAMIC symbol size % does not match dynamic " @@ -1952,7 +1949,7 @@ msgstr "" "розділ [%2d] «%s»: розмір символу _DYNAMIC % не відповідає розміру " "динамічного сегмента %\n" -#: src/elflint.c:1059 +#: src/elflint.c:1063 #, c-format msgid "" "section [%2d] '%s': symbol %zu: symbol in dynamic symbol table with non-" @@ -1961,29 +1958,29 @@ msgstr "" "розділ [%2d] «%s»: символ %zu: символ у динамічній таблиці символів з " "нетиповою видимістю\n" -#: src/elflint.c:1063 +#: src/elflint.c:1067 #, c-format msgid "section [%2d] '%s': symbol %zu: unknown bit set in st_other\n" msgstr "розділ [%2d] «%s»: символ %zu: невідомий набір бітів у st_other\n" -#: src/elflint.c:1101 +#: src/elflint.c:1105 #, c-format msgid "section [%2d] '%s': cannot get section data.\n" msgstr "розділ [%2d] «%s»: не вдалося отримати дані розділу.\n" -#: src/elflint.c:1117 +#: src/elflint.c:1121 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n" msgstr "розділ [%2d] «%s»: для цього розділу RELA використано DT_RELCOUNT\n" -#: src/elflint.c:1128 src/elflint.c:1181 +#: src/elflint.c:1132 src/elflint.c:1185 #, c-format msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n" msgstr "" "розділ [%2d] «%s»: значення DT_RELCOUNT %d є занадто високим для цього " "розділу\n" -#: src/elflint.c:1153 src/elflint.c:1206 +#: src/elflint.c:1157 src/elflint.c:1210 #, c-format msgid "" "section [%2d] '%s': relative relocations after index %d as specified by " @@ -1992,7 +1989,7 @@ msgstr "" "розділ [%2d] «%s»: відносні пересування після позиції %d, вказаної за " "допомогою DT_RELCOUNT\n" -#: src/elflint.c:1159 src/elflint.c:1212 +#: src/elflint.c:1163 src/elflint.c:1216 #, c-format msgid "" "section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT " @@ -2001,52 +1998,53 @@ msgstr "" "розділ [%2d] «%s»: безвідносне пересування на позиції %zu; DT_RELCOUNT " "визначено %d відносних пересування\n" -#: src/elflint.c:1171 +#: src/elflint.c:1175 #, c-format msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n" msgstr "розділ [%2d] «%s»: для цього розділу REL використано DT_RELACOUNT\n" -#: src/elflint.c:1254 +#: src/elflint.c:1258 #, c-format msgid "section [%2d] '%s': invalid destination section index\n" msgstr "розділ [%2d] «%s»: некоректний індекс розділу призначення\n" -#: src/elflint.c:1266 +#: src/elflint.c:1270 #, c-format msgid "section [%2d] '%s': invalid destination section type\n" msgstr "розділ [%2d] «%s»: некоректний тип розділу призначення\n" -#: src/elflint.c:1274 +#: src/elflint.c:1278 #, c-format msgid "section [%2d] '%s': sh_info should be zero\n" msgstr "розділ [%2d] «%s»: sh_info має бути нульовим\n" -#: src/elflint.c:1282 -#, fuzzy, c-format +#: src/elflint.c:1286 +#, c-format msgid "" "section [%2d] '%s': no relocations for merge-able string sections possible\n" msgstr "" -"розділ [%2d] «%s»: пересування у придатних до об’єднання розділах неможливе\n" +"розділ [%2d] «%s»: неможливі пересування для розділів рядків, які непридатні " +"до об'єднання\n" -#: src/elflint.c:1290 +#: src/elflint.c:1294 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n" msgstr "" "розділ [%2d] «%s»: розмірність запису розділу не відповідає ElfXX_Rela\n" -#: src/elflint.c:1350 +#: src/elflint.c:1354 #, c-format msgid "text relocation flag set but there is no read-only segment\n" msgstr "" "встановлено прапорець пересування тексту, але сегмент придатний лише до " "читання\n" -#: src/elflint.c:1377 +#: src/elflint.c:1381 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid type\n" msgstr "розділ [%2d] «%s»: пересування %zu: некоректний тип\n" -#: src/elflint.c:1385 +#: src/elflint.c:1389 #, c-format msgid "" "section [%2d] '%s': relocation %zu: relocation type invalid for the file " @@ -2055,12 +2053,12 @@ msgstr "" "розділ [%2d] «%s»: пересування %zu: некоректний тип пересування для типу " "файла\n" -#: src/elflint.c:1393 +#: src/elflint.c:1397 #, c-format msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n" msgstr "розділ [%2d] «%s»: пересування %zu: некоректний індекс символу\n" -#: src/elflint.c:1411 +#: src/elflint.c:1415 #, c-format msgid "" "section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can " @@ -2069,12 +2067,12 @@ msgstr "" "розділ [%2d] «%s»: пересування %zu: з %s можна використовувати лише символ " "«_GLOBAL_OFFSET_TABLE_»\n" -#: src/elflint.c:1428 +#: src/elflint.c:1432 #, c-format msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n" msgstr "розділ [%2d] «%s»: пересування %zu: зміщення за межі діапазону\n" -#: src/elflint.c:1443 +#: src/elflint.c:1447 #, c-format msgid "" "section [%2d] '%s': relocation %zu: copy relocation against symbol of type " @@ -2083,7 +2081,7 @@ msgstr "" "розділ [%2d] «%s»: пересування %zu: пересування копіювання для символу типу " "%s\n" -#: src/elflint.c:1464 +#: src/elflint.c:1468 #, c-format msgid "" "section [%2d] '%s': relocation %zu: read-only section modified but text " @@ -2092,22 +2090,22 @@ msgstr "" "розділ [%2d] «%s»: пересування %zu: змінено придатний лише для читання " "розділ, але не встановлено прапорець пересування тексту\n" -#: src/elflint.c:1479 +#: src/elflint.c:1483 #, c-format msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n" msgstr "розділ [%2d] «%s»: пересування завантажених і незавантажених даних\n" -#: src/elflint.c:1519 src/elflint.c:1570 +#: src/elflint.c:1523 src/elflint.c:1574 #, c-format msgid "section [%2d] '%s': cannot get relocation %zu: %s\n" msgstr "розділ [%2d] «%s»: не вдалося отримати зміщення %zu: %s\n" -#: src/elflint.c:1646 +#: src/elflint.c:1650 #, c-format msgid "more than one dynamic section present\n" msgstr "вказано більше одного динамічного розділу\n" -#: src/elflint.c:1664 +#: src/elflint.c:1668 #, c-format msgid "" "section [%2d]: referenced as string table for section [%2d] '%s' but section " @@ -2116,46 +2114,46 @@ msgstr "" "розділ [%2d]: надано посилання на таблицю рядків розділу [%2d] «%s», але " "значення посилання на розділ є некоректним\n" -#: src/elflint.c:1672 +#: src/elflint.c:1676 #, c-format msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n" msgstr "" "розділ [%2d] «%s»: розмірність запису розділу не відповідає ElfXX_Dyn\n" -#: src/elflint.c:1677 src/elflint.c:1966 +#: src/elflint.c:1681 src/elflint.c:1970 #, c-format msgid "section [%2d] '%s': sh_info not zero\n" msgstr "розділ [%2d] «%s»: sh_info не є нульовим\n" -#: src/elflint.c:1687 +#: src/elflint.c:1691 #, c-format msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n" msgstr "" "розділ [%2d] «%s»: не вдалося отримати запис динамічного розділу %zu: %s\n" -#: src/elflint.c:1695 +#: src/elflint.c:1699 #, c-format msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n" msgstr "" "розділ [%2d] «%s»: за записом DT_NULL вказано записи, що не належать до " "DT_NULL\n" -#: src/elflint.c:1702 +#: src/elflint.c:1706 #, c-format msgid "section [%2d] '%s': entry %zu: unknown tag\n" msgstr "розділ [%2d] «%s»: запис %zu: невідома мітка\n" -#: src/elflint.c:1713 +#: src/elflint.c:1717 #, c-format msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n" msgstr "розділ [%2d] «%s»: запис %zu: декілька записів з міткою %s\n" -#: src/elflint.c:1723 +#: src/elflint.c:1727 #, c-format msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n" msgstr "розділ [%2d] «%s»: запис %zu: використано мітку рівня 2 %s\n" -#: src/elflint.c:1741 +#: src/elflint.c:1745 #, c-format msgid "" "section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n" @@ -2163,7 +2161,7 @@ msgstr "" "розділ [%2d] «%s»: запис %zu: значенням DT_PLTREL має бути DT_REL або " "DT_RELA\n" -#: src/elflint.c:1754 +#: src/elflint.c:1758 #, c-format msgid "" "section [%2d] '%s': entry %zu: pointer does not match address of section " @@ -2172,7 +2170,7 @@ msgstr "" "розділ [%2d] «%s»: розділ %zu: вказівник не відповідає адресі розділу [%2d] " "«%s», на яку посилається sh_link\n" -#: src/elflint.c:1797 +#: src/elflint.c:1801 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must point into loaded segment\n" @@ -2180,7 +2178,7 @@ msgstr "" "розділ [%2d] «%s»: запис %zu: значення %s має вказувати на завантажений " "сегмент\n" -#: src/elflint.c:1812 +#: src/elflint.c:1816 #, c-format msgid "" "section [%2d] '%s': entry %zu: %s value must be valid offset in section " @@ -2189,48 +2187,48 @@ msgstr "" "розділ [%2d] «%s»: запис %zu: значенням %s має бути коректне зміщення у " "розділі [%2d] «%s»\n" -#: src/elflint.c:1832 src/elflint.c:1860 +#: src/elflint.c:1836 src/elflint.c:1864 #, c-format msgid "section [%2d] '%s': contains %s entry but not %s\n" msgstr "розділ [%2d] «%s»: містить запис %s, але не %s\n" -#: src/elflint.c:1844 +#: src/elflint.c:1848 #, c-format msgid "section [%2d] '%s': mandatory tag %s not present\n" msgstr "розділ [%2d] «%s»: немає обов’язкової мітки %s\n" -#: src/elflint.c:1853 +#: src/elflint.c:1857 #, c-format msgid "section [%2d] '%s': no hash section present\n" msgstr "розділ [%2d] «%s»: не виявлено розділу хешів\n" -#: src/elflint.c:1868 src/elflint.c:1875 +#: src/elflint.c:1872 src/elflint.c:1879 #, c-format msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n" msgstr "розділ [%2d] «%s»: вказано не всі зі значень %s, %s і %s\n" -#: src/elflint.c:1885 src/elflint.c:1889 +#: src/elflint.c:1889 src/elflint.c:1893 #, c-format msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n" msgstr "" "розділ [%2d] «%s»: у DSO, позначеному на кроці попереднього компонування, " "немає мітки %s\n" -#: src/elflint.c:1895 +#: src/elflint.c:1899 #, c-format msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n" msgstr "" "розділ [%2d] «%s»: під час попереднього компонування як залежність позначено " "файл, який не є файлом DSO\n" -#: src/elflint.c:1906 src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 +#: src/elflint.c:1910 src/elflint.c:1914 src/elflint.c:1918 src/elflint.c:1922 #, c-format msgid "section [%2d] '%s': %s tag missing in prelinked executable\n" msgstr "" "розділ [%2d] «%s»: у попередньо скомпонованому виконуваному файлі не " "міститься мітки %s\n" -#: src/elflint.c:1930 +#: src/elflint.c:1934 #, c-format msgid "" "section [%2d] '%s': only relocatable files can have extended section index\n" @@ -2238,7 +2236,7 @@ msgstr "" "розділ [%2d] «%s»: розширений розділ покажчика можуть мати лише файли, " "придатні до пересування\n" -#: src/elflint.c:1940 +#: src/elflint.c:1944 #, c-format msgid "" "section [%2d] '%s': extended section index section not for symbol table\n" @@ -2246,29 +2244,29 @@ msgstr "" "розділ [%2d] «%s»: розділ розширеного покажчика розділів не призначено для " "таблиць символів\n" -#: src/elflint.c:1944 +#: src/elflint.c:1948 #, c-format msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n" msgstr "" "розділ [%2d] «%s»: індекс розширеного розділу sh_link [%2d] є некоректним\n" -#: src/elflint.c:1949 +#: src/elflint.c:1953 #, c-format msgid "cannot get data for symbol section\n" msgstr "не вдалося отримати дані для розділу символів\n" -#: src/elflint.c:1952 +#: src/elflint.c:1956 #, c-format msgid "section [%2d] '%s': entry size does not match Elf32_Word\n" msgstr "розділ [%2d] «%s»: розмірність запису не відповідає Elf32_Word\n" -#: src/elflint.c:1961 +#: src/elflint.c:1965 #, c-format msgid "section [%2d] '%s': extended index table too small for symbol table\n" msgstr "" "розділ [%2d] «%s»: розширена таблиця покажчика замала для таблиці символів\n" -#: src/elflint.c:1976 +#: src/elflint.c:1980 #, c-format msgid "" "section [%2d] '%s': extended section index in section [%2zu] '%s' refers to " @@ -2277,24 +2275,24 @@ msgstr "" "розділ [%2d] «%s»: розширений покажчик розділів у розділі [%2zu] «%s» " "посилається на ту саму таблицю розділів\n" -#: src/elflint.c:1994 +#: src/elflint.c:1998 #, c-format msgid "symbol 0 should have zero extended section index\n" msgstr "символу 0 має відповідати нульовий індекс розширеного розділу\n" -#: src/elflint.c:2006 +#: src/elflint.c:2010 #, c-format msgid "cannot get data for symbol %zu\n" msgstr "не вдалося отримати дані для символу %zu\n" -#: src/elflint.c:2011 +#: src/elflint.c:2015 #, c-format msgid "extended section index is % but symbol index is not XINDEX\n" msgstr "" "індекс розширеного розділу дорівнює %, але індекс символу не є " "XINDEX\n" -#: src/elflint.c:2028 src/elflint.c:2085 +#: src/elflint.c:2032 src/elflint.c:2089 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n" @@ -2302,43 +2300,43 @@ msgstr "" "розділ [%2d] «%s»: розділ таблиці хешів занадто малий (розмір %ld, мало бути " "— %ld)\n" -#: src/elflint.c:2042 src/elflint.c:2099 +#: src/elflint.c:2046 src/elflint.c:2103 #, c-format msgid "section [%2d] '%s': chain array too large\n" msgstr "розділ [%2d] «%s»: масив ланцюжка занадто великий\n" -#: src/elflint.c:2056 src/elflint.c:2113 +#: src/elflint.c:2060 src/elflint.c:2117 #, c-format msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n" msgstr "" "розділ [%2d] «%s»: посилання на хеш блоку %zu лежить поза межами діапазону\n" -#: src/elflint.c:2066 +#: src/elflint.c:2070 #, c-format msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n" msgstr "" "розділ [%2d] «%s»: посилання ланцюжка хешів %zu лежить поза межами " "діапазону\n" -#: src/elflint.c:2123 +#: src/elflint.c:2127 #, c-format msgid "section [%2d] '%s': hash chain reference % out of bounds\n" msgstr "" "розділ [%2d] «%s»: посилання ланцюжка хешів % лежить поза межами " "діапазону\n" -#: src/elflint.c:2136 +#: src/elflint.c:2140 #, c-format msgid "section [%2d] '%s': not enough data\n" msgstr "розділ [%2d] «%s»: недостатньо даних\n" -#: src/elflint.c:2148 +#: src/elflint.c:2152 #, c-format msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n" msgstr "" "розділ [%2d] «%s»: розмір бітової маски є нульовим або не є степенем 2: %u\n" -#: src/elflint.c:2164 +#: src/elflint.c:2168 #, c-format msgid "" "section [%2d] '%s': hash table section is too small (is %ld, expected at " @@ -2347,12 +2345,12 @@ msgstr "" "розділ [%2d] «%s»: розділ таблиці хешів є надто малим (маємо %ld, мало бути " "принаймні %ld)\n" -#: src/elflint.c:2173 +#: src/elflint.c:2177 #, c-format msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n" msgstr "розділ [%2d] «%s»: зсув 2-ої функції хешування занадто великий: %u\n" -#: src/elflint.c:2207 +#: src/elflint.c:2211 #, c-format msgid "" "section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n" @@ -2360,7 +2358,7 @@ msgstr "" "розділ [%2d] '%s': ланцюжок хешів для блоку %zu розташовано нижче за позицію " "відхилення індексу символу\n" -#: src/elflint.c:2228 +#: src/elflint.c:2232 #, c-format msgid "" "section [%2d] '%s': symbol %u referenced in chain for bucket %zu is " @@ -2369,7 +2367,7 @@ msgstr "" "розділ [%2d] «%s»: символ %u, на який посилається ланцюжок у блоці %zu не " "визначено\n" -#: src/elflint.c:2241 +#: src/elflint.c:2245 #, c-format msgid "" "section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n" @@ -2377,7 +2375,7 @@ msgstr "" "розділ [%2d] «%s»: значення хешу для символу %u у ланцюжку для блоку %zu є " "помилковим\n" -#: src/elflint.c:2250 +#: src/elflint.c:2254 #, c-format msgid "" "section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n" @@ -2385,14 +2383,14 @@ msgstr "" "розділ [%2d] «%s»: індекс маски для символу %u у ланцюжку для блоку %zu є " "помилковим\n" -#: src/elflint.c:2280 +#: src/elflint.c:2284 #, c-format msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n" msgstr "" "розділ [%2d] «%s»: ланцюжок хешів для блоку %zu лежить поза межами " "діапазону\n" -#: src/elflint.c:2285 +#: src/elflint.c:2289 #, c-format msgid "" "section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n" @@ -2400,43 +2398,43 @@ msgstr "" "розділ [%2d] «%s»: посилання на символ у ланцюжку для блоку %zu лежить поза " "межами діапазону\n" -#: src/elflint.c:2291 +#: src/elflint.c:2295 #, c-format msgid "section [%2d] '%s': bitmask does not match names in the hash table\n" msgstr "розділ [%2d] «%s»: бітова маска не відповідає назвам у таблиці хешів\n" -#: src/elflint.c:2304 +#: src/elflint.c:2308 #, c-format msgid "section [%2d] '%s': relocatable files cannot have hash tables\n" msgstr "" "розділ [%2d] «%s»: придатні до пересування файли не можуть містити таблиць " "хешів\n" -#: src/elflint.c:2322 +#: src/elflint.c:2326 #, c-format msgid "section [%2d] '%s': hash table not for dynamic symbol table\n" msgstr "" "розділ [%2d] «%s»: таблицю хешів не призначено для зберігання таблиці " "динамічних символів\n" -#: src/elflint.c:2326 +#: src/elflint.c:2330 #, c-format msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n" msgstr "" "розділ [%2d] «%s»: некоректний індекс розділу таблиці символів sh_link " "[%2d]\n" -#: src/elflint.c:2336 +#: src/elflint.c:2340 #, c-format msgid "section [%2d] '%s': hash table entry size incorrect\n" msgstr "розділ [%2d] «%s»: розмірність запису таблиці хешів є некоректною\n" -#: src/elflint.c:2341 +#: src/elflint.c:2345 #, c-format msgid "section [%2d] '%s': not marked to be allocated\n" msgstr "розділ [%2d] «%s»: не позначено для пересування\n" -#: src/elflint.c:2346 +#: src/elflint.c:2350 #, c-format msgid "" "section [%2d] '%s': hash table has not even room for initial administrative " @@ -2445,27 +2443,27 @@ msgstr "" "розділ [%2d] «%s»: у таблиці хешів виявлено незвичайне розташування " "початкових адміністративних записів\n" -#: src/elflint.c:2395 +#: src/elflint.c:2399 #, c-format msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n" msgstr "sh_link у розділах хешів [%2zu] «%s» і [%2zu] «%s» не збігаються\n" -#: src/elflint.c:2419 src/elflint.c:2484 src/elflint.c:2519 +#: src/elflint.c:2423 src/elflint.c:2488 src/elflint.c:2523 #, c-format msgid "hash section [%2zu] '%s' does not contain enough data\n" msgstr "розділ хешу [%2zu] «%s» містить недостатньо даних\n" -#: src/elflint.c:2440 +#: src/elflint.c:2444 #, c-format msgid "hash section [%2zu] '%s' has zero bit mask words\n" msgstr "розділ хешу [%2zu] «%s» містить нульові слова бітової маски\n" -#: src/elflint.c:2451 src/elflint.c:2495 src/elflint.c:2532 +#: src/elflint.c:2455 src/elflint.c:2499 src/elflint.c:2536 #, c-format msgid "hash section [%2zu] '%s' uses too much data\n" msgstr "розділ хешу [%2zu] «%s» використовує надто багато даних\n" -#: src/elflint.c:2466 +#: src/elflint.c:2470 #, c-format msgid "" "hash section [%2zu] '%s' invalid symbol index % (max_nsyms: " @@ -2474,17 +2472,17 @@ msgstr "" "розділ хешу [%2zu] «%s» некоректний індекс символу % (макс. к-ть " "символів: %, кількість записів: %\n" -#: src/elflint.c:2553 +#: src/elflint.c:2557 #, c-format msgid "hash section [%2zu] '%s' invalid sh_entsize\n" msgstr "розділ хешу [%2zu] «%s» некоректне значення sh_entsize\n" -#: src/elflint.c:2563 src/elflint.c:2567 +#: src/elflint.c:2567 src/elflint.c:2571 #, c-format msgid "section [%2zu] '%s': reference to symbol index 0\n" msgstr "розділ [%2zu] «%s»: посилання на індекс символів 0\n" -#: src/elflint.c:2574 +#: src/elflint.c:2578 #, c-format msgid "" "symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash " @@ -2493,7 +2491,7 @@ msgstr "" "виявлено посилання на символ %d у новій таблиці хешів у [%2zu] «%s», але " "його немає у старій таблиці хешів у [%2zu] «%s»\n" -#: src/elflint.c:2586 +#: src/elflint.c:2590 #, c-format msgid "" "symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash " @@ -2502,12 +2500,12 @@ msgstr "" "виявлено посилання на символ %d у старій таблиці хешів у [%2zu] «%s», але " "його немає у новій таблиці хешів у [%2zu] «%s»\n" -#: src/elflint.c:2602 +#: src/elflint.c:2606 #, c-format msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n" msgstr "розділ [%2d] «%s»: ненульове значення sh_%s для розділу NULL\n" -#: src/elflint.c:2622 +#: src/elflint.c:2626 #, c-format msgid "" "section [%2d] '%s': section groups only allowed in relocatable object files\n" @@ -2515,95 +2513,95 @@ msgstr "" "розділ [%2d] «%s»: групи розділів передбачено лише для придатних до " "пересування об’єктних файлах\n" -#: src/elflint.c:2633 +#: src/elflint.c:2637 #, c-format msgid "section [%2d] '%s': cannot get symbol table: %s\n" msgstr "розділ [%2d] «%s»: не вдалося отримати таблицю символів: %s\n" -#: src/elflint.c:2638 +#: src/elflint.c:2642 #, c-format msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n" msgstr "" "розділ [%2d] «%s»: посилання на розділ у sh_link не має таблиці символів\n" -#: src/elflint.c:2644 +#: src/elflint.c:2648 #, c-format msgid "section [%2d] '%s': invalid symbol index in sh_info\n" msgstr "розділ [%2d] «%s»: некоректний індекс символу у sh_info\n" -#: src/elflint.c:2649 +#: src/elflint.c:2653 #, c-format msgid "section [%2d] '%s': sh_flags not zero\n" msgstr "розділ [%2d] «%s»: sh_flags не є нульовим\n" -#: src/elflint.c:2656 +#: src/elflint.c:2660 #, c-format msgid "section [%2d] '%s': cannot get symbol for signature\n" msgstr "розділ [%2d] «%s»: не вдалося отримати символ для підпису\n" -#: src/elflint.c:2660 +#: src/elflint.c:2664 #, c-format msgid "section [%2d] '%s': cannot get symbol name for signature\n" msgstr "розділ [%2d] «%s»: не вдалося отримати назву символу для підпису\n" -#: src/elflint.c:2665 +#: src/elflint.c:2669 #, c-format msgid "section [%2d] '%s': signature symbol cannot be empty string\n" msgstr "розділ [%2d] «%s»: символ підпису не може бути порожнім рядком\n" -#: src/elflint.c:2671 +#: src/elflint.c:2675 #, c-format msgid "section [%2d] '%s': sh_flags not set correctly\n" msgstr "розділ [%2d] «%s»: для sh_flags встановлено помилкове значення\n" -#: src/elflint.c:2677 +#: src/elflint.c:2681 #, c-format msgid "section [%2d] '%s': cannot get data: %s\n" msgstr "розділ [%2d] «%s»: не вдалося отримати дані: %s\n" -#: src/elflint.c:2686 +#: src/elflint.c:2690 #, c-format msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n" msgstr "розділ [%2d] «%s»: розмір розділу не є кратним до sizeof(Elf32_Word)\n" -#: src/elflint.c:2692 +#: src/elflint.c:2696 #, c-format msgid "section [%2d] '%s': section group without flags word\n" msgstr "розділ [%2d] «%s»: група розділів без значення типу word прапорців\n" -#: src/elflint.c:2700 +#: src/elflint.c:2704 #, c-format msgid "section [%2d] '%s': section group without member\n" msgstr "розділ [%2d] «%s»: група розділів без елементів\n" -#: src/elflint.c:2704 +#: src/elflint.c:2708 #, c-format msgid "section [%2d] '%s': section group with only one member\n" msgstr "розділ [%2d] «%s»: група розділів, що містить лише один елемент\n" -#: src/elflint.c:2715 +#: src/elflint.c:2719 #, c-format msgid "section [%2d] '%s': unknown section group flags\n" msgstr "розділ [%2d] «%s»: невідомі прапорці групи розділів\n" -#: src/elflint.c:2727 +#: src/elflint.c:2731 #, c-format msgid "section [%2d] '%s': section index %zu out of range\n" msgstr "розділ [%2d] «%s»: індекс розділу %zu поза межами діапазону\n" -#: src/elflint.c:2736 +#: src/elflint.c:2740 #, c-format msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n" msgstr "" "розділ [%2d] «%s»: не вдалося отримати заголовок розділу для елемента %zu: " "%s\n" -#: src/elflint.c:2743 +#: src/elflint.c:2747 #, c-format msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n" msgstr "розділ [%2d] «%s»: група розділів містить іншу групу [%2d] «%s»\n" -#: src/elflint.c:2749 +#: src/elflint.c:2753 #, c-format msgid "" "section [%2d] '%s': element %zu references section [%2d] '%s' without " @@ -2612,12 +2610,12 @@ msgstr "" "розділ [%2d] «%s»: елемент %zu посилається на розділ [%2d] «%s» без " "встановленого прапорця SHF_GROUP\n" -#: src/elflint.c:2756 +#: src/elflint.c:2760 #, c-format msgid "section [%2d] '%s' is contained in more than one section group\n" msgstr "розділ [%2d] «%s» міститься у більше ніж одній групі розділів\n" -#: src/elflint.c:2946 +#: src/elflint.c:2950 #, c-format msgid "" "section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no " @@ -2626,7 +2624,7 @@ msgstr "" "розділ [%2d] «%s» посилається у sh_link на розділ [%2d] «%s», який не має " "динамічної таблиці символів\n" -#: src/elflint.c:2958 +#: src/elflint.c:2962 #, c-format msgid "" "section [%2d] '%s' has different number of entries than symbol table [%2d] " @@ -2635,28 +2633,28 @@ msgstr "" "кількість записів у розділі [%2d] «%s» відрізняється від кількості у таблиці " "символів [%2d] «%s»\n" -#: src/elflint.c:2974 +#: src/elflint.c:2978 #, c-format msgid "section [%2d] '%s': symbol %d: cannot read version data\n" msgstr "розділ [%2d] «%s»: символ %d: не вдалося прочитати дані щодо версії\n" -#: src/elflint.c:2990 +#: src/elflint.c:2994 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n" msgstr "" "розділ [%2d] «%s»: символ %d: локальний символ у загальному контексті\n" -#: src/elflint.c:2998 +#: src/elflint.c:3002 #, c-format msgid "section [%2d] '%s': symbol %d: local symbol with version\n" msgstr "розділ [%2d] «%s»: символ %d: локальний символ з версією\n" -#: src/elflint.c:3012 +#: src/elflint.c:3016 #, c-format msgid "section [%2d] '%s': symbol %d: invalid version index %d\n" msgstr "розділ [%2d] «%s»: символ %d: некоректний індекс версії %d\n" -#: src/elflint.c:3017 +#: src/elflint.c:3021 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for defined version\n" @@ -2664,7 +2662,7 @@ msgstr "" "розділ [%2d] «%s»: символ %d: індекси версії %d призначено до визначеної " "версії\n" -#: src/elflint.c:3027 +#: src/elflint.c:3031 #, c-format msgid "" "section [%2d] '%s': symbol %d: version index %d is for requested version\n" @@ -2672,45 +2670,45 @@ msgstr "" "розділ [%2d] «%s»: символ %d: індекс версії %d призначено для версії, на яку " "надійшов запит\n" -#: src/elflint.c:3080 +#: src/elflint.c:3084 #, c-format msgid "more than one version reference section present\n" msgstr "виявлено більше за один розділ посилань на версії\n" -#: src/elflint.c:3088 src/elflint.c:3235 +#: src/elflint.c:3092 src/elflint.c:3239 #, c-format msgid "section [%2d] '%s': sh_link does not link to string table\n" msgstr "розділ [%2d] «%s»: sh_link не посилається на таблицю рядків\n" -#: src/elflint.c:3113 src/elflint.c:3289 +#: src/elflint.c:3117 src/elflint.c:3293 #, c-format msgid "section [%2d] '%s': entry %d has wrong version %d\n" msgstr "розділ [%2d] «%s»: запис %d має помилкову версію %d\n" -#: src/elflint.c:3120 src/elflint.c:3296 +#: src/elflint.c:3124 src/elflint.c:3300 #, c-format msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n" msgstr "" "розділ [%2d] «%s»: запис %d містить помилкове зміщення у допоміжних даних\n" -#: src/elflint.c:3130 +#: src/elflint.c:3134 #, c-format msgid "section [%2d] '%s': entry %d has invalid file reference\n" msgstr "розділ [%2d] «%s»: запис %d містить некоректне посилання на файл\n" -#: src/elflint.c:3138 +#: src/elflint.c:3142 #, c-format msgid "section [%2d] '%s': entry %d references unknown dependency\n" msgstr "розділ [%2d] «%s»: запис %d посилається на невідому залежність\n" -#: src/elflint.c:3150 +#: src/elflint.c:3154 #, c-format msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n" msgstr "" "розділ [%2d] «%s»: допоміжний запис %d запису %d позначено невідомим " "прапорцем\n" -#: src/elflint.c:3158 +#: src/elflint.c:3162 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has invalid name " @@ -2719,7 +2717,7 @@ msgstr "" "розділ [%2d] «%s»: допоміжний запис %d запису %d містить некоректне " "посилання на назву\n" -#: src/elflint.c:3167 +#: src/elflint.c:3171 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: " @@ -2728,7 +2726,7 @@ msgstr "" "розділ [%2d] «%s»: допоміжний запис %d запису %d має помилкове значення " "хешу: %#x, мало бути %#x\n" -#: src/elflint.c:3176 +#: src/elflint.c:3180 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version " @@ -2737,7 +2735,7 @@ msgstr "" "розділ [%2d] «%s»: допоміжний запис %d запису %d містить дублікати назви " "версії «%s»\n" -#: src/elflint.c:3187 +#: src/elflint.c:3191 #, c-format msgid "" "section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n" @@ -2745,13 +2743,13 @@ msgstr "" "розділ [%2d] «%s»: допоміжний запис %d запису %d має помилкове наступне " "поле\n" -#: src/elflint.c:3204 src/elflint.c:3380 +#: src/elflint.c:3208 src/elflint.c:3384 #, c-format msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n" msgstr "" "розділ [%2d] «%s»: запис %d має некоректне зміщення щодо наступного запису\n" -#: src/elflint.c:3212 src/elflint.c:3388 +#: src/elflint.c:3216 src/elflint.c:3392 #, c-format msgid "" "section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says " @@ -2760,44 +2758,44 @@ msgstr "" "розділ [%2d] «%s»: запис %d має нульове зміщення щодо наступного запису, але " "за sh_info можна зрозуміти, що записів більше\n" -#: src/elflint.c:3227 +#: src/elflint.c:3231 #, c-format msgid "more than one version definition section present\n" msgstr "виявлено більше за один розділ визначення версій\n" -#: src/elflint.c:3274 +#: src/elflint.c:3278 #, c-format msgid "section [%2d] '%s': more than one BASE definition\n" msgstr "розділ [%2d] «%s»: повторне визначення BASE\n" -#: src/elflint.c:3278 +#: src/elflint.c:3282 #, c-format msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n" msgstr "" "розділ [%2d] «%s»: визначення BASE повинно мати індекс VER_NDX_GLOBAL\n" -#: src/elflint.c:3284 +#: src/elflint.c:3288 #, c-format msgid "section [%2d] '%s': entry %d has unknown flag\n" msgstr "розділ [%2d] «%s»: невідомий прапорець запису %d\n" -#: src/elflint.c:3311 +#: src/elflint.c:3315 #, c-format msgid "section [%2d] '%s': entry %d has invalid name reference\n" msgstr "розділ [%2d] «%s»: запис %d містить некоректне посилання на назву\n" -#: src/elflint.c:3318 +#: src/elflint.c:3322 #, c-format msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n" msgstr "" "розділ [%2d] «%s»: запис %d має помилкове значення хешу: %#x, мало бути %#x\n" -#: src/elflint.c:3326 +#: src/elflint.c:3330 #, c-format msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n" msgstr "розділ [%2d] «%s»: запис %d містить дублікати назви версії «%s»\n" -#: src/elflint.c:3346 +#: src/elflint.c:3350 #, c-format msgid "" "section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n" @@ -2805,53 +2803,53 @@ msgstr "" "розділ [%2d] «%s»: запис %d містить некоректне посилання на назву у " "допоміжних даних\n" -#: src/elflint.c:3363 +#: src/elflint.c:3367 #, c-format msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n" msgstr "" "розділ [%2d] «%s»: у допоміжних даних запису %d міститься помилкове поле " "наступного запису\n" -#: src/elflint.c:3396 +#: src/elflint.c:3400 #, c-format msgid "section [%2d] '%s': no BASE definition\n" msgstr "розділ [%2d] «%s»: немає визначення BASE\n" -#: src/elflint.c:3412 +#: src/elflint.c:3416 #, c-format msgid "section [%2d] '%s': unknown parent version '%s'\n" msgstr "розділ [%2d] «%s»: невідома основна версія «%s»\n" -#: src/elflint.c:3425 +#: src/elflint.c:3429 #, c-format msgid "section [%2d] '%s': empty object attributes section\n" msgstr "розділ [%2d] «%s»: порожній розділ атрибутів об’єкта\n" -#: src/elflint.c:3446 +#: src/elflint.c:3450 #, c-format msgid "section [%2d] '%s': unrecognized attribute format\n" msgstr "розділ [%2d] «%s»: не вдалося визначити формат атрибутів\n" -#: src/elflint.c:3462 +#: src/elflint.c:3466 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute section\n" msgstr "" "розділ [%2d] «%s»: зміщення %zu: поле нульового розміру у розділі атрибутів\n" -#: src/elflint.c:3471 +#: src/elflint.c:3475 #, c-format msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n" msgstr "" "розділ [%2d] «%s»: зміщення %zu: некоректна довжина у розділі атрибутів\n" -#: src/elflint.c:3483 +#: src/elflint.c:3487 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n" msgstr "" "розділ [%2d] «%s»: зміщення %zu: незавершений рядок назви постачальника\n" -#: src/elflint.c:3500 +#: src/elflint.c:3504 #, c-format msgid "" "section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n" @@ -2859,12 +2857,12 @@ msgstr "" "розділ [%2d] «%s»: зміщення %zu: незавершене поле ULEB128 у тезі підрозділу " "атрибутів\n" -#: src/elflint.c:3509 +#: src/elflint.c:3513 #, c-format msgid "section [%2d] '%s': offset %zu: truncated attribute section\n" msgstr "розділ [%2d] «%s»: зміщення %zu: обрізаний розділ атрибутів\n" -#: src/elflint.c:3518 +#: src/elflint.c:3522 #, c-format msgid "" "section [%2d] '%s': offset %zu: zero length field in attribute subsection\n" @@ -2872,7 +2870,7 @@ msgstr "" "розділ [%2d] «%s»: зміщення %zu: поле нульового розміру у підрозділі " "атрибутів\n" -#: src/elflint.c:3533 +#: src/elflint.c:3537 #, c-format msgid "" "section [%2d] '%s': offset %zu: invalid length in attribute subsection\n" @@ -2880,7 +2878,7 @@ msgstr "" "розділ [%2d] «%s»: зміщення %zu: некоректна довжина у підрозділі атрибутів\n" #. Tag_File -#: src/elflint.c:3544 +#: src/elflint.c:3548 #, c-format msgid "" "section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n" @@ -2888,35 +2886,35 @@ msgstr "" "розділ [%2d] «%s»: зміщення %zu: підрозділ атрибутів містить неочікуваний " "теґ %u\n" -#: src/elflint.c:3562 +#: src/elflint.c:3566 #, c-format msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n" msgstr "" "розділ [%2d] «%s»: зміщення %zu: незавершене поле ULEB128 у тезі атрибуту\n" -#: src/elflint.c:3573 +#: src/elflint.c:3577 #, c-format msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n" msgstr "розділ [%2d] «%s»: зміщення %zu: незавершений рядок у атрибуті\n" -#: src/elflint.c:3586 +#: src/elflint.c:3590 #, c-format msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n" msgstr "розділ [%2d] «%s»: зміщення %zu: незавершений теґ атрибуту %u\n" -#: src/elflint.c:3590 +#: src/elflint.c:3594 #, c-format msgid "" "section [%2d] '%s': offset %zu: unrecognized %s attribute value %\n" msgstr "" "розділ [%2d] «%s»: зміщення %zu: невідоме значення %s атрибуту %\n" -#: src/elflint.c:3600 +#: src/elflint.c:3604 #, c-format msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n" msgstr "розділ [%2d] «%s»: зміщення %zu: невідомий постачальник «%s»\n" -#: src/elflint.c:3606 +#: src/elflint.c:3610 #, c-format msgid "" "section [%2d] '%s': offset %zu: extra bytes after last attribute section\n" @@ -2924,47 +2922,47 @@ msgstr "" "розділ [%2d] «%s»: зміщення %zu: зайві байти після останнього розділу " "атрибутів\n" -#: src/elflint.c:3695 +#: src/elflint.c:3699 #, c-format msgid "cannot get section header of zeroth section\n" msgstr "не вдалося отримати заголовок нульового розділу\n" -#: src/elflint.c:3699 +#: src/elflint.c:3703 #, c-format msgid "zeroth section has nonzero name\n" msgstr "нульовий розділ має ненульову назву\n" -#: src/elflint.c:3701 +#: src/elflint.c:3705 #, c-format msgid "zeroth section has nonzero type\n" msgstr "нульовий розділ має ненульовий тип\n" -#: src/elflint.c:3703 +#: src/elflint.c:3707 #, c-format msgid "zeroth section has nonzero flags\n" msgstr "нульовий розділ має ненульові прапорці\n" -#: src/elflint.c:3705 +#: src/elflint.c:3709 #, c-format msgid "zeroth section has nonzero address\n" msgstr "нульовий розділ має ненульову адресу\n" -#: src/elflint.c:3707 +#: src/elflint.c:3711 #, c-format msgid "zeroth section has nonzero offset\n" msgstr "нульовий розділ має ненульове зміщення\n" -#: src/elflint.c:3709 +#: src/elflint.c:3713 #, c-format msgid "zeroth section has nonzero align value\n" msgstr "нульовий розділ має ненульове значення вирівнювання\n" -#: src/elflint.c:3711 +#: src/elflint.c:3715 #, c-format msgid "zeroth section has nonzero entry size value\n" msgstr "нульовий розділ має ненульове значення розміру запису\n" -#: src/elflint.c:3714 +#: src/elflint.c:3718 #, c-format msgid "" "zeroth section has nonzero size value while ELF header has nonzero shnum " @@ -2973,7 +2971,7 @@ msgstr "" "нульовий розділ має ненульове значення розміру, хоча заголовок ELF ман " "ненульове значення shnum\n" -#: src/elflint.c:3718 +#: src/elflint.c:3722 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " @@ -2982,7 +2980,7 @@ msgstr "" "нульовий розділ має ненульове значення компонування, хоча у заголовку ELF " "немає сигналу переповнення у shstrndx\n" -#: src/elflint.c:3722 +#: src/elflint.c:3726 #, c-format msgid "" "zeroth section has nonzero link value while ELF header does not signal " @@ -2991,28 +2989,28 @@ msgstr "" "нульовий розділ має ненульове значення компонування, хоча у заголовку ELF " "немає сигналу переповнення у phnum\n" -#: src/elflint.c:3740 +#: src/elflint.c:3744 #, c-format msgid "cannot get section header for section [%2zu] '%s': %s\n" msgstr "не вдалося отримати заголовок розділу [%2zu] «%s»: %s\n" -#: src/elflint.c:3749 +#: src/elflint.c:3753 #, c-format msgid "section [%2zu]: invalid name\n" msgstr "розділ [%2zu]: некоректна назва\n" -#: src/elflint.c:3776 +#: src/elflint.c:3780 #, c-format msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n" msgstr "" "розділ [%2d] «%s» належить до помилкового типу: мав бути %s, маємо %s\n" -#: src/elflint.c:3794 +#: src/elflint.c:3798 #, c-format msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n" msgstr "розділ [%2zu] «%s» має помилкові прапорці: мало бути %s, маємо %s\n" -#: src/elflint.c:3812 +#: src/elflint.c:3816 #, c-format msgid "" "section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n" @@ -3020,12 +3018,12 @@ msgstr "" "розділ [%2zu] «%s» має помилкові прапорці: мало бути %s, можливо, %s, але " "маємо %s\n" -#: src/elflint.c:3830 +#: src/elflint.c:3834 #, c-format msgid "section [%2zu] '%s' present in object file\n" msgstr "у об’єктному файлі виявлено розділ [%2zu] «%s»\n" -#: src/elflint.c:3836 src/elflint.c:3868 +#: src/elflint.c:3840 src/elflint.c:3872 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n" @@ -3033,7 +3031,7 @@ msgstr "" "у розділ [%2zu] «%s» встановлено прапорець SHF_ALLOC, але немає придатного " "до завантаження сегмента\n" -#: src/elflint.c:3841 src/elflint.c:3873 +#: src/elflint.c:3845 src/elflint.c:3877 #, c-format msgid "" "section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable " @@ -3042,7 +3040,7 @@ msgstr "" "у розділі [%2zu] «%s» не встановлено прапорець SHF_ALLOC, але є придатні до " "завантаження сегменти\n" -#: src/elflint.c:3849 +#: src/elflint.c:3853 #, c-format msgid "" "section [%2zu] '%s' is extension section index table in non-object file\n" @@ -3050,22 +3048,22 @@ msgstr "" "розділ [%2zu] «%s» є таблицею-покажчиком розділу розширень у файлі, який не " "є об’єктним\n" -#: src/elflint.c:3892 +#: src/elflint.c:3896 #, c-format msgid "section [%2zu] '%s': size not multiple of entry size\n" msgstr "розділ [%2zu] «%s»: розмір не є кратним до розміру запису\n" -#: src/elflint.c:3897 +#: src/elflint.c:3901 #, c-format msgid "cannot get section header\n" msgstr "не вдалося отримати заголовок розділу\n" -#: src/elflint.c:3907 +#: src/elflint.c:3911 #, c-format msgid "section [%2zu] '%s' has unsupported type %d\n" msgstr "розділ [%2zu] «%s» належить до непідтримуваного типу %d\n" -#: src/elflint.c:3922 +#: src/elflint.c:3926 #, c-format msgid "" "section [%2zu] '%s' contains invalid processor-specific flag(s) %#\n" @@ -3073,74 +3071,74 @@ msgstr "" "розділ [%2zu] «%s» містить некоректні специфічні для процесора прапорці " "%#\n" -#: src/elflint.c:3929 +#: src/elflint.c:3933 #, c-format msgid "section [%2zu] '%s' contains unknown flag(s) %#\n" msgstr "розділ [%2zu] «%s» містить невідомі прапорці %#\n" -#: src/elflint.c:3937 +#: src/elflint.c:3941 #, c-format msgid "section [%2zu] '%s': thread-local data sections address not zero\n" msgstr "" "розділ [%2zu] «%s»: адреса розділів локальних даних потоків не є нульовою\n" -#: src/elflint.c:3947 -#, fuzzy, c-format +#: src/elflint.c:3951 +#, c-format msgid "section [%2zu] '%s': allocated section cannot be compressed\n" msgstr "" -"розділ [%2zu] «%s»: адреса розділів локальних даних потоків не є нульовою\n" +"розділ [%2zu] «%s»: розміщений у пам'яті розділ не може бути стиснений\n" -#: src/elflint.c:3952 -#, fuzzy, c-format +#: src/elflint.c:3956 +#, c-format msgid "section [%2zu] '%s': nobits section cannot be compressed\n" -msgstr "розділ [%2d] «%s»: не виявлено розділу хешів\n" +msgstr "розділ [%2zu] «%s»: розділ nobits не може бути стиснений\n" -#: src/elflint.c:3958 -#, fuzzy, c-format +#: src/elflint.c:3962 +#, c-format msgid "" "section [%2zu] '%s': compressed section with no compression header: %s\n" -msgstr "розділ [%2d] «%s»: група розділів, що містить лише один елемент\n" +msgstr "розділ [%2zu] «%s»: стиснений розділ без заголовка стиснення: %s\n" -#: src/elflint.c:3964 +#: src/elflint.c:3968 #, c-format msgid "section [%2zu] '%s': invalid section reference in link value\n" msgstr "" "розділ [%2zu] «%s»: некоректне посилання на розділ у значенні компонування\n" -#: src/elflint.c:3969 +#: src/elflint.c:3973 #, c-format msgid "section [%2zu] '%s': invalid section reference in info value\n" msgstr "" "розділ [%2zu] «%s»: некоректне посилання на розділ у значенні відомостей\n" -#: src/elflint.c:3976 +#: src/elflint.c:3980 #, c-format msgid "section [%2zu] '%s': strings flag set without merge flag\n" msgstr "розділ [%2zu] «%s»: встановлено прапорець strings без прапорця merge\n" -#: src/elflint.c:3981 +#: src/elflint.c:3985 #, c-format msgid "section [%2zu] '%s': merge flag set but entry size is zero\n" msgstr "" "розділ [%2zu] «%s»: встановлено прапорець merge, але розмір запису є " "нульовим\n" -#: src/elflint.c:4000 +#: src/elflint.c:4004 #, c-format msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n" msgstr "розділ [%2zu] «%s» має неочікуваний тип %d для виконуваного розділу\n" -#: src/elflint.c:4009 -#, fuzzy, c-format +#: src/elflint.c:4013 +#, c-format msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n" -msgstr "розділ [%2zu] «%s» не повинен бути придатним до запису\n" +msgstr "розділ [%2zu] «%s» у файлах debuginfo має належати до типу NOBITS\n" -#: src/elflint.c:4016 +#: src/elflint.c:4020 #, c-format msgid "section [%2zu] '%s' is both executable and writable\n" msgstr "розділ [%2zu] «%s» є одночасно виконуваним і придатним до запису\n" -#: src/elflint.c:4047 +#: src/elflint.c:4051 #, c-format msgid "" "section [%2zu] '%s' not fully contained in segment of program header entry " @@ -3149,7 +3147,7 @@ msgstr "" "розділ [%2zu] «%s» не повністю міститься у сегменті запису заголовка " "програми %d\n" -#: src/elflint.c:4057 +#: src/elflint.c:4061 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " @@ -3158,7 +3156,7 @@ msgstr "" "розділ [%2zu] «%s» належить до типу NOBITS, але його читання виконується з " "файла у сегментів запису заголовка програми %d\n" -#: src/elflint.c:4083 +#: src/elflint.c:4087 #, c-format msgid "" "section [%2zu] '%s' has type NOBITS but is read from the file in segment of " @@ -3167,7 +3165,7 @@ msgstr "" "розділ [%2zu] «%s» належить до типу NOBITS, але його читання виконується з " "файла у сегментів запису заголовка програми %d, а вміст файла є ненульовим\n" -#: src/elflint.c:4094 +#: src/elflint.c:4098 #, c-format msgid "" "section [%2zu] '%s' has not type NOBITS but is not read from the file in " @@ -3176,19 +3174,19 @@ msgstr "" "розділ [%2zu] «%s» не належить до типу NOBITS, але його читання не " "виконується з файла у сегментів запису заголовка програми %d\n" -#: src/elflint.c:4105 +#: src/elflint.c:4109 #, c-format msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n" msgstr "розділ [%2zu] «%s» є виконуваним у невиконуваному сегменті %d\n" -#: src/elflint.c:4115 +#: src/elflint.c:4119 #, c-format msgid "section [%2zu] '%s' is writable in unwritable segment %d\n" msgstr "" "розділ [%2zu] «%s» є придатним до запису у непридатному до запису сегменті " "%d\n" -#: src/elflint.c:4125 +#: src/elflint.c:4129 #, c-format msgid "" "section [%2zu] '%s': alloc flag set but section not in any loaded segment\n" @@ -3196,7 +3194,7 @@ msgstr "" "розділ [%2zu] «%s»: встановлено прапорець alloc, але розділ не перебуває у " "жодному завантаженому сегменті\n" -#: src/elflint.c:4131 +#: src/elflint.c:4135 #, c-format msgid "" "section [%2zu] '%s': ELF header says this is the section header string table " @@ -3205,7 +3203,7 @@ msgstr "" "розділ [%2zu] «%s»: заголовок ELF повідомляє про те, що це таблиця рядків " "заголовка розділу, але ця таблиця не належить до типу SHT_TYPE\n" -#: src/elflint.c:4139 +#: src/elflint.c:4143 #, c-format msgid "" "section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n" @@ -3213,17 +3211,17 @@ msgstr "" "розділ [%2zu] «%s»: придатні до пересування файли не можуть містити " "динамічних таблиць символів\n" -#: src/elflint.c:4190 +#: src/elflint.c:4194 #, c-format msgid "more than one version symbol table present\n" msgstr "виявлено більше за одну таблицю символів версій\n" -#: src/elflint.c:4213 +#: src/elflint.c:4217 #, c-format msgid "INTERP program header entry but no .interp section\n" msgstr "існує запис заголовка програми INTERP, але не розділ .interp\n" -#: src/elflint.c:4224 +#: src/elflint.c:4228 #, c-format msgid "" "loadable segment [%u] is executable but contains no executable sections\n" @@ -3231,14 +3229,14 @@ msgstr "" "придатний до завантаження сегмент [%u] є виконуваним, але не містить " "виконуваних розділів\n" -#: src/elflint.c:4230 +#: src/elflint.c:4234 #, c-format msgid "loadable segment [%u] is writable but contains no writable sections\n" msgstr "" "придатний до завантаження розділ [%u] є придатним до запису, але не містить " "придатних до запису розділів\n" -#: src/elflint.c:4241 +#: src/elflint.c:4245 #, c-format msgid "" "no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section " @@ -3247,24 +3245,24 @@ msgstr "" "немає розділу .gnu.versym, хоча існує розділ .gnu.versym_d або .gnu." "versym_r\n" -#: src/elflint.c:4254 +#: src/elflint.c:4258 #, c-format msgid "duplicate version index %d\n" msgstr "дублікат індексу версії %d\n" -#: src/elflint.c:4268 +#: src/elflint.c:4272 #, c-format msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n" msgstr "" "існує розділ .gnu.versym, але немає розділу .gnu.versym_d або .gnu.versym_r\n" -#: src/elflint.c:4317 +#: src/elflint.c:4321 #, c-format msgid "phdr[%d]: unknown core file note type % at offset %\n" msgstr "" "phdr[%d]: невідомий тип нотатки файла core % за зміщенням %\n" -#: src/elflint.c:4321 +#: src/elflint.c:4325 #, c-format msgid "" "section [%2d] '%s': unknown core file note type % at offset %zu\n" @@ -3272,56 +3270,57 @@ msgstr "" "розділ [%2d] «%s»: невідомий тип нотатки файла core % за зміщенням " "%zu\n" -#: src/elflint.c:4370 -#, fuzzy, c-format +#: src/elflint.c:4374 +#, c-format msgid "" "phdr[%d]: unknown object file note type % with owner name '%s' at " "offset %zu\n" msgstr "" -"phdr[%d]: невідомий тип нотатки об’єктного файла % за зміщенням %zu\n" +"phdr[%d]: невідомий тип нотатки у файлі об'єктів, %, із іменем " +"власника «%s» за зміщенням %zu\n" -#: src/elflint.c:4375 -#, fuzzy, c-format +#: src/elflint.c:4379 +#, c-format msgid "" "section [%2d] '%s': unknown object file note type % with owner name " "'%s' at offset %zu\n" msgstr "" -"розділ [%2d] «%s»: невідомий тип нотатки об’єктного файла % за " -"зміщенням %zu\n" +"розділ [%2d] «%s»: невідомий тип нотатки у файлі об'єктів, %, із " +"іменем власника «%s» за зміщенням %zu\n" -#: src/elflint.c:4394 +#: src/elflint.c:4398 #, c-format msgid "phdr[%d]: no note entries defined for the type of file\n" msgstr "phdr[%d]: для цього типу файлів не визначено записів нотаток\n" -#: src/elflint.c:4414 +#: src/elflint.c:4418 #, c-format msgid "phdr[%d]: cannot get content of note section: %s\n" msgstr "phdr[%d]: не вдалося отримати вміст розділу нотаток: %s\n" -#: src/elflint.c:4417 +#: src/elflint.c:4421 #, c-format msgid "phdr[%d]: extra % bytes after last note\n" msgstr "phdr[%d]: зайві % байтів після останнього запису нотатки\n" -#: src/elflint.c:4438 +#: src/elflint.c:4442 #, c-format msgid "section [%2d] '%s': no note entries defined for the type of file\n" msgstr "" "розділ [%2d] «%s»: для цього типу файлів не визначено записів нотаток\n" -#: src/elflint.c:4445 +#: src/elflint.c:4449 #, c-format msgid "section [%2d] '%s': cannot get content of note section\n" msgstr "розділ [%2d] «%s»: не вдалося отримати вміст розділу нотаток\n" -#: src/elflint.c:4448 +#: src/elflint.c:4452 #, c-format msgid "section [%2d] '%s': extra % bytes after last note\n" msgstr "" "розділ [%2d] «%s»: додаткові % байтів після останньої нотатки\n" -#: src/elflint.c:4466 +#: src/elflint.c:4470 #, c-format msgid "" "only executables, shared objects, and core files can have program headers\n" @@ -3329,141 +3328,143 @@ msgstr "" "заголовки програм можуть бути лише у виконуваних файлів, об’єктних файлів " "спільного використання або файлів core\n" -#: src/elflint.c:4481 +#: src/elflint.c:4485 #, c-format msgid "cannot get program header entry %d: %s\n" msgstr "не вдалося отримати запис заголовка програми %d: %s\n" -#: src/elflint.c:4490 +#: src/elflint.c:4499 #, c-format msgid "program header entry %d: unknown program header entry type %#\n" msgstr "" "запис заголовка програми %d: невідомий тип запису заголовка програми " "%#\n" -#: src/elflint.c:4501 +#: src/elflint.c:4510 #, c-format msgid "more than one INTERP entry in program header\n" msgstr "більше за один запис INTERP у заголовку програми\n" -#: src/elflint.c:4509 +#: src/elflint.c:4518 #, c-format msgid "more than one TLS entry in program header\n" msgstr "більше за один запис TLS у заголовку програми\n" -#: src/elflint.c:4516 +#: src/elflint.c:4525 #, c-format msgid "static executable cannot have dynamic sections\n" msgstr "у статичному виконуваному файлі не може бути динамічних розділів\n" -#: src/elflint.c:4530 +#: src/elflint.c:4539 #, c-format msgid "dynamic section reference in program header has wrong offset\n" msgstr "" "посилання на динамічний розділ у заголовку програми має помилкове зміщення\n" -#: src/elflint.c:4533 +#: src/elflint.c:4542 #, c-format msgid "dynamic section size mismatch in program and section header\n" msgstr "" "розміри динамічного розділу у заголовку програми та у заголовку розділу не " "збігаються\n" -#: src/elflint.c:4543 +#: src/elflint.c:4552 #, c-format msgid "more than one GNU_RELRO entry in program header\n" msgstr "більше за один запис GNU_RELRO у заголовку програми\n" -#: src/elflint.c:4564 +#: src/elflint.c:4573 #, c-format msgid "loadable segment GNU_RELRO applies to is not writable\n" msgstr "" "придатний до завантаження сегмент, до якого звертається GNU_RELRO, " "непридатний до запису\n" -#: src/elflint.c:4575 +#: src/elflint.c:4584 #, c-format msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n" msgstr "" "прапорці придатного до завантаження сегмента [%u] не відповідають прапорцям " "GNU_RELRO [%u]\n" -#: src/elflint.c:4582 +#: src/elflint.c:4591 #, c-format msgid "" "GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n" msgstr "" +"прапорці GNU_RELRO [%u] не є підмножиною прапорців завантажуваного сегмента " +"[%u]\n" -#: src/elflint.c:4591 src/elflint.c:4614 +#: src/elflint.c:4600 src/elflint.c:4623 #, c-format msgid "%s segment not contained in a loaded segment\n" msgstr "сегмент %s не міститься у завантаженому сегменті\n" -#: src/elflint.c:4620 +#: src/elflint.c:4629 #, c-format msgid "program header offset in ELF header and PHDR entry do not match" msgstr "зміщення заголовка програми у заголовку ELF і запис PHDR не збігаються" -#: src/elflint.c:4647 +#: src/elflint.c:4656 #, c-format msgid "call frame search table reference in program header has wrong offset\n" msgstr "" "посилання на таблицю вікон викликів у заголовку програми має помилкове " "зміщення\n" -#: src/elflint.c:4650 +#: src/elflint.c:4659 #, c-format msgid "call frame search table size mismatch in program and section header\n" msgstr "" "розміри таблиці пошуку вікон виклику у заголовку програми та у заголовку " "розділу не збігаються\n" -#: src/elflint.c:4663 +#: src/elflint.c:4672 #, c-format msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n" msgstr "існує PT_GNU_EH_FRAME, хоча немає розділу .eh_frame_hdr\n" -#: src/elflint.c:4671 +#: src/elflint.c:4680 #, c-format msgid "call frame search table must be allocated\n" msgstr "таблицю пошуку вікон викликів має бути розміщено у пам’яті\n" -#: src/elflint.c:4674 +#: src/elflint.c:4683 #, c-format msgid "section [%2zu] '%s' must be allocated\n" msgstr "розділ [%2zu] «%s» має бути розміщено у пам’яті\n" -#: src/elflint.c:4678 +#: src/elflint.c:4687 #, c-format msgid "call frame search table must not be writable\n" msgstr "таблиця пошуку вікон викликів не повинна бути придатною до запису\n" -#: src/elflint.c:4681 +#: src/elflint.c:4690 #, c-format msgid "section [%2zu] '%s' must not be writable\n" msgstr "розділ [%2zu] «%s» не повинен бути придатним до запису\n" -#: src/elflint.c:4686 +#: src/elflint.c:4695 #, c-format msgid "call frame search table must not be executable\n" msgstr "таблиця пошуку вікон викликів не повинна бути придатною до виконання\n" -#: src/elflint.c:4689 +#: src/elflint.c:4698 #, c-format msgid "section [%2zu] '%s' must not be executable\n" msgstr "розділ [%2zu] «%s» не повинен бути придатним до виконання\n" -#: src/elflint.c:4700 +#: src/elflint.c:4709 #, c-format msgid "program header entry %d: file size greater than memory size\n" msgstr "запис заголовка програми %d: розмір файла перевищує об’єм пам’яті\n" -#: src/elflint.c:4707 +#: src/elflint.c:4716 #, c-format msgid "program header entry %d: alignment not a power of 2\n" msgstr "запис заголовка програми %d: значення вирівнювання не є степенем 2\n" -#: src/elflint.c:4710 +#: src/elflint.c:4719 #, c-format msgid "" "program header entry %d: file offset and virtual address not module of " @@ -3472,7 +3473,7 @@ msgstr "" "запис заголовка програми %d: зміщення у файлі і віртуальна адреса не " "співвідносяться з вирівнюванням\n" -#: src/elflint.c:4723 +#: src/elflint.c:4732 #, c-format msgid "" "executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME " @@ -3481,12 +3482,12 @@ msgstr "" "виконуваний модуль/DSO з розділом .eh_frame_hdr не містить запису заголовка " "програми PT_GNU_EH_FRAME" -#: src/elflint.c:4757 +#: src/elflint.c:4766 #, c-format msgid "cannot read ELF header: %s\n" msgstr "не вдалося прочитати заголовок ELF: %s\n" -#: src/elflint.c:4783 +#: src/elflint.c:4792 #, c-format msgid "text relocation flag set but not needed\n" msgstr "" @@ -3793,9 +3794,9 @@ msgid "%s: size of section %zd `%s' is not multiple of entry size" msgstr "%s: розмір розділу %zd «%s» не є кратним до розміру запису" #: src/nm.c:1300 -#, fuzzy, c-format +#, c-format msgid "%s: entries (%zd) in section %zd `%s' is too large" -msgstr "%s: розмір запису у розділі %zd «%s» не є очікуваним" +msgstr "%s: записи (%zd) у розділі %zd, «%s» є завеликим" #. XXX Add machine specific object file types. #: src/nm.c:1527 @@ -3920,6 +3921,8 @@ msgid "" "Used with -w to find the skeleton Compile Units in FILE associated with the " "Split Compile units in a .dwo input file" msgstr "" +"Використовується з -w для пошуку основи компільованих модулів у ФАЙЛі, " +"пов'язаному із модулями розділеної компіляції у вхідному файлі .dwo" #: src/readelf.c:104 msgid "ELF output selection:" @@ -3950,23 +3953,20 @@ msgid "Display relocations" msgstr "Показувати пересування" #: src/readelf.c:114 -#, fuzzy msgid "Display the section groups" -msgstr "Показувати заголовки розділів" +msgstr "Показувати групи розділів" #: src/readelf.c:115 msgid "Display the sections' headers" msgstr "Показувати заголовки розділів" #: src/readelf.c:118 -#, fuzzy msgid "Display the symbol table sections" -msgstr "Показувати таблицю символів" +msgstr "Показати розділи таблиці символів" #: src/readelf.c:120 -#, fuzzy msgid "Display (only) the dynamic symbol table" -msgstr "Показувати лише зовнішні символи" +msgstr "Показувати (лише) динамічну таблицю символів" #: src/readelf.c:121 msgid "Display versioning information" @@ -3989,15 +3989,14 @@ msgid "Additional output selection:" msgstr "Додатковий вибір виводу:" #: src/readelf.c:130 -#, fuzzy msgid "" "Display DWARF section content. SECTION can be one of abbrev, addr, aranges, " "decodedaranges, frame, gdb_index, info, info+, loc, line, decodedline, " "ranges, pubnames, str, macinfo, macro or exception" msgstr "" -"Показати вміст розділу DWARF. Значенням РОЗДІЛ може бути abbrev, aranges, " -"decodedaranges, frame, gdb_index, info, loc, line, decodedline, ranges, " -"pubnames, str, macinfo, macro або exception" +"Показати вміст розділу DWARF. Значенням РОЗДІЛ може бути abbrev, addr, " +"aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, " +"decodedline, ranges, pubnames, str, macinfo, macro або exception" #: src/readelf.c:134 msgid "Dump the uninterpreted contents of SECTION, by number or name" @@ -4035,6 +4034,8 @@ msgid "" "Show compression information for compressed sections (when used with -S); " "decompress section before dumping data (when used with -p or -x)" msgstr "" +"Показати дані щодо стискання для стиснених розділів (якщо використано з -S); " +"розпакувати розділ до створення дампу даних (якщо використано з -p або -x)" #. Short description of program. #: src/readelf.c:154 @@ -4151,9 +4152,9 @@ msgid "cannot determine number of program headers: %s" msgstr "не вдалося визначити кількість заголовків програми: %s" #: src/readelf.c:991 -#, fuzzy, c-format +#, c-format msgid "cannot read ELF: %s" -msgstr "не вдалося прочитати %s: %s" +msgstr "не вдалося прочитати ELF: %s" #: src/readelf.c:1052 msgid "NONE (None)" @@ -4237,9 +4238,9 @@ msgid " Machine: %s\n" msgstr " Архітектура: %s\n" #: src/readelf.c:1107 -#, fuzzy, c-format +#, c-format msgid " Machine: : 0x%x\n" -msgstr " Архітектура: %s\n" +msgstr " Архітектура: <невідома>: 0x%x\n" #: src/readelf.c:1110 #, c-format @@ -4338,23 +4339,23 @@ msgstr "" "\n" #: src/readelf.c:1228 src/readelf.c:1436 -#, fuzzy, c-format +#, c-format msgid "cannot get number of sections: %s" -msgstr "не вдалося визначити кількість розділів: %s" +msgstr "не вдалося отримати кількість розділів: %s" #: src/readelf.c:1231 -#, fuzzy, c-format +#, c-format msgid "" "There are %zd section headers, starting at offset %#:\n" "\n" msgstr "" -"Виявлено %d заголовків розділів, зміщення початку — %#:\n" +"Виявлено %zd заголовків розділів, зміщення початку — %#:\n" "\n" #: src/readelf.c:1240 -#, fuzzy, c-format +#, c-format msgid "cannot get section header string table index: %s" -msgstr "не вдалося визначити індекс заголовка розділу у таблиці рядків" +msgstr "не вдалося визначити індекс заголовка розділу у таблиці рядків: %s" #: src/readelf.c:1243 msgid "Section Headers:" @@ -4378,21 +4379,21 @@ msgstr "" #: src/readelf.c:1253 msgid " [Compression Size Al]" -msgstr "" +msgstr " [Стискання Розмір Ал]" #: src/readelf.c:1255 msgid " [Compression Size Al]" -msgstr "" +msgstr " [Стискання Розмір Ал]" #: src/readelf.c:1331 -#, fuzzy, c-format +#, c-format msgid "bad compression header for section %zd: %s" -msgstr "не вдалося отримати заголовок розділу %zu: %s" +msgstr "помилковий заголовок стиснення для розділу %zd: %s" #: src/readelf.c:1342 -#, fuzzy, c-format +#, c-format msgid "bad gnu compressed size for section %zd: %s" -msgstr "не вдалося отримати дані для розділу %d: %s" +msgstr "помилкове значення стисненого розміру gnu для розділу %zd: %s" #: src/readelf.c:1360 msgid "Program Headers:" @@ -4479,12 +4480,12 @@ msgstr "<НЕКОРЕКТНИЙ РОЗДІЛ>" #: src/readelf.c:1656 src/readelf.c:2383 src/readelf.c:3484 src/readelf.c:12517 #: src/readelf.c:12524 src/readelf.c:12568 src/readelf.c:12575 msgid "Couldn't uncompress section" -msgstr "" +msgstr "Не вдалося розпакувати розділ" #: src/readelf.c:1661 src/readelf.c:2388 src/readelf.c:3489 -#, fuzzy, c-format +#, c-format msgid "cannot get section [%zd] header: %s" -msgstr "не вдалося отримати заголовок розділу: %s" +msgstr "не вдалося отримати заголовок розділу [%zd]: %s" #: src/readelf.c:1805 src/readelf.c:2455 src/readelf.c:2713 src/readelf.c:2789 #: src/readelf.c:3093 src/readelf.c:3167 src/readelf.c:5364 @@ -4836,9 +4837,9 @@ msgid "invalid data in sysv.hash section %d" msgstr "некоректні дані у розділі sysv.hash %d" #: src/readelf.c:3271 -#, fuzzy, c-format +#, c-format msgid "invalid chain in sysv.hash section %d" -msgstr "некоректні дані у розділі sysv.hash %d" +msgstr "некоректний ланцюжок у розділі sysv.hash %d" #: src/readelf.c:3306 #, c-format @@ -4846,9 +4847,9 @@ msgid "invalid data in sysv.hash64 section %d" msgstr "некоректні дані у розділі sysv.hash64 %d" #: src/readelf.c:3337 -#, fuzzy, c-format +#, c-format msgid "invalid chain in sysv.hash64 section %d" -msgstr "некоректні дані у розділі sysv.hash64 %d" +msgstr "некоректний ланцюжок у розділі sysv.hash64 %d" #: src/readelf.c:3373 #, c-format @@ -4952,9 +4953,9 @@ msgid " %u: %s\n" msgstr " %u: %s\n" #: src/readelf.c:3823 -#, fuzzy, c-format +#, c-format msgid "sprintf failure" -msgstr "помилка mprotect" +msgstr "помилка sprintf" #: src/readelf.c:4305 msgid "empty block" @@ -4966,9 +4967,9 @@ msgid "%zu byte block:" msgstr "%zu-байтовий блок:" #: src/readelf.c:4786 -#, fuzzy, c-format +#, c-format msgid "%*s[%2] %s \n" -msgstr "%*s[%4] %s <ОБРІЗАНО>\n" +msgstr "%*s[%2] %s <ОБРІЗАНО>\n" #: src/readelf.c:4850 #, c-format @@ -4986,9 +4987,9 @@ msgid "%s %# used with different base addresses" msgstr "%s %# використано з різними базовими адресами" #: src/readelf.c:4871 -#, fuzzy, c-format +#, c-format msgid "%s %# used with different attribute %s and %s" -msgstr "%s %# використано з різними розмірами адрес" +msgstr "%s %# використано з різними атрибутами, %s і %s" #: src/readelf.c:4968 #, c-format @@ -5043,38 +5044,36 @@ msgstr "" "Розділ DWARF [%2zu] «%s» зі зміщенням %#:\n" #: src/readelf.c:5137 -#, fuzzy, c-format +#, c-format msgid "cannot get .debug_addr section data: %s" -msgstr "не вдалося отримати дані розділу: %s" +msgstr "не вдалося отримати дані розділу .debug_addr: %s" #: src/readelf.c:5237 src/readelf.c:5261 src/readelf.c:5645 src/readelf.c:9054 -#, fuzzy, c-format +#, c-format msgid " Length: %8\n" -msgstr "" -"\n" -" Довжина: %6\n" +msgstr " Довжина: %8\n" #: src/readelf.c:5239 src/readelf.c:5276 src/readelf.c:5658 src/readelf.c:9067 -#, fuzzy, c-format +#, c-format msgid " DWARF version: %8\n" -msgstr " версія DWARF: %6\n" +msgstr " версія DWARF: %8\n" #: src/readelf.c:5240 src/readelf.c:5285 src/readelf.c:5667 src/readelf.c:9076 -#, fuzzy, c-format +#, c-format msgid " Address size: %8\n" -msgstr " Розмір адреси: %6\n" +msgstr " Розмір адреси: %8\n" #: src/readelf.c:5242 src/readelf.c:5295 src/readelf.c:5677 src/readelf.c:9086 -#, fuzzy, c-format +#, c-format msgid " Segment size: %8\n" msgstr "" -" Розмір сегмента: %6\n" +" Розмір сегмента: %8\n" "\n" #: src/readelf.c:5280 src/readelf.c:5662 src/readelf.c:9071 src/readelf.c:10435 -#, fuzzy, c-format +#, c-format msgid "Unknown version" -msgstr "невідома версія" +msgstr "Невідома версія" #: src/readelf.c:5290 src/readelf.c:5503 src/readelf.c:5672 src/readelf.c:9081 #, c-format @@ -5181,58 +5180,62 @@ msgid " %zu padding bytes\n" msgstr " %zu байтів доповнення\n" #: src/readelf.c:5609 -#, fuzzy, c-format +#, c-format msgid "cannot get .debug_rnglists content: %s" -msgstr "не вдалося отримати дані .debug_ranges: %s" +msgstr "не вдалося отримати вміст .debug_rnglists: %s" #: src/readelf.c:5632 src/readelf.c:9041 -#, fuzzy, c-format +#, c-format msgid "" "Table at Offset 0x%:\n" "\n" -msgstr " зміщення .debug_line: 0x%\n" +msgstr "" +"Таблиця за зміщенням 0x%:\n" +"\n" #: src/readelf.c:5687 src/readelf.c:9096 -#, fuzzy, c-format +#, c-format msgid " Offset entries: %8\n" -msgstr " Довжина зміщення: %\n" +msgstr " Записи зміщення: %8\n" #: src/readelf.c:5703 src/readelf.c:9112 #, c-format msgid " Unknown CU base: " -msgstr "" +msgstr " Невідома основа CU: " #: src/readelf.c:5705 src/readelf.c:9114 #, c-format msgid " CU [%6] base: " -msgstr "" +msgstr " Основа CU [%6]: " #: src/readelf.c:5711 src/readelf.c:9120 #, c-format msgid " Not associated with a CU.\n" -msgstr "" +msgstr " Не пов'язано із CU.\n" #: src/readelf.c:5722 src/readelf.c:9131 #, c-format msgid "too many offset entries for unit length" -msgstr "" +msgstr "забагато записів зсуву для довжини модуля" #: src/readelf.c:5726 src/readelf.c:9135 -#, fuzzy, c-format +#, c-format msgid " Offsets starting at 0x%:\n" -msgstr " Зміщення: 0x%\n" +msgstr " Зміщення, що починаються з 0x%:\n" #: src/readelf.c:5778 -#, fuzzy, c-format +#, c-format msgid "invalid range list data" -msgstr "некоректні дані" +msgstr "некоректні дані списку діапазонів" #: src/readelf.c:5963 src/readelf.c:9423 -#, fuzzy, c-format +#, c-format msgid "" " %zu padding bytes\n" "\n" -msgstr " %zu байтів доповнення\n" +msgstr "" +" %zu байтів доповнення\n" +"\n" #: src/readelf.c:5980 #, c-format @@ -5245,6 +5248,8 @@ msgid "" "\n" " Unknown CU base: " msgstr "" +"\n" +" Невідома основа CU: " #: src/readelf.c:6018 src/readelf.c:9480 #, c-format @@ -5252,6 +5257,8 @@ msgid "" "\n" " CU [%6] base: " msgstr "" +"\n" +" Основа CU [%6]: " #: src/readelf.c:6027 src/readelf.c:9506 src/readelf.c:9532 #, c-format @@ -5259,16 +5266,18 @@ msgid " [%6tx] \n" msgstr " [%6tx] <НЕКОРЕКТНІ ДАНІ>\n" #: src/readelf.c:6048 src/readelf.c:9612 -#, fuzzy, c-format +#, c-format msgid "" " [%6tx] base address\n" " " -msgstr " [%6tx] базова адреса %s\n" +msgstr "" +" [%6tx] базова адреса\n" +" " #: src/readelf.c:6056 src/readelf.c:9620 -#, fuzzy, c-format +#, c-format msgid " [%6tx] empty list\n" -msgstr " [%6tx] порожній список\n" +msgstr " [%6tx] порожній список\n" #: src/readelf.c:6311 msgid " \n" @@ -5326,34 +5335,34 @@ msgid " %-26sLSDA pointer: %#\n" msgstr " %-26sвказівник LSDA: %#\n" #: src/readelf.c:6993 -#, fuzzy, c-format +#, c-format msgid "DIE [%] cannot get attribute code: %s" -msgstr "не вдалося отримати код атрибута: %s" +msgstr "DIE [%] не вдалося отримати код атрибута: %s" #: src/readelf.c:7003 -#, fuzzy, c-format +#, c-format msgid "DIE [%] cannot get attribute form: %s" -msgstr "не вдалося отримати форму атрибута: %s" +msgstr "DIE [%] не вдалося отримати форму атрибута: %s" #: src/readelf.c:7025 -#, fuzzy, c-format +#, c-format msgid "DIE [%] cannot get attribute '%s' (%s) value: %s" -msgstr "не вдалося отримати значення атрибута: %s" +msgstr "DIE [%] не вдалося отримати значення атрибута «%s» (%s): %s" #: src/readelf.c:7355 -#, fuzzy, c-format +#, c-format msgid "invalid file (%): %s" -msgstr "некоректний файл" +msgstr "некоректний файл (%): %s" #: src/readelf.c:7359 -#, fuzzy, c-format +#, c-format msgid "no srcfiles for CU [%]" -msgstr " встановити файл у %\n" +msgstr "немає srcfiles для CU [%]" #: src/readelf.c:7363 -#, fuzzy, c-format +#, c-format msgid "couldn't get DWARF CU: %s" -msgstr "не вдалося отримати ELF: %s" +msgstr "не вдалося отримати CU DWARF: %s" #: src/readelf.c:7676 #, c-format @@ -5367,12 +5376,12 @@ msgstr "" " [Зміщення]\n" #: src/readelf.c:7726 -#, fuzzy, c-format +#, c-format msgid "cannot get next unit: %s" -msgstr "не вдалося визначити наступний DIE: %s" +msgstr "не вдалося отримати наступний модуль: %s" #: src/readelf.c:7745 -#, fuzzy, c-format +#, c-format msgid "" " Type unit at offset %:\n" " Version: %, Abbreviation section offset: %, Address size: " @@ -5380,9 +5389,9 @@ msgid "" " Type signature: %#, Type offset: %# [%]\n" msgstr "" " Модуль типів за зміщенням %:\n" -" Версія: %, Зміщення розділу скорочень: %, Адреса: %, " -"Зміщення: %\n" -" Підпис типу: %#, Зміщення типу: %#\n" +" Версія: %, Зміщення розділу скорочень: %, Розмір адреси: " +"%, Розмір зміщення: %\n" +" Підпис типу: %#, Зміщення типу: %# [%]\n" #: src/readelf.c:7757 #, c-format @@ -5398,12 +5407,12 @@ msgstr "" #: src/readelf.c:7767 src/readelf.c:7930 #, c-format msgid " Unit type: %s (%)" -msgstr "" +msgstr " Тип модуля: %s (%)" #: src/readelf.c:7794 #, c-format msgid "unknown version (%d) or unit type (%d)" -msgstr "" +msgstr "невідома версія (%d) або тип модуля (%d)" #: src/readelf.c:7823 #, c-format @@ -5411,10 +5420,10 @@ msgid "cannot get DIE offset: %s" msgstr "не вдалося отримати зміщення DIE: %s" #: src/readelf.c:7832 -#, fuzzy, c-format +#, c-format msgid "cannot get tag of DIE at offset [%] in section '%s': %s" msgstr "" -"не вдалося отримати мітку DIE за зміщенням % у розділі «%s»: %s" +"не вдалося отримати мітку DIE за зміщенням [%] у розділі «%s»: %s" #: src/readelf.c:7870 #, c-format @@ -5427,13 +5436,13 @@ msgid "cannot get next DIE: %s" msgstr "не вдалося визначити наступний DIE: %s" #: src/readelf.c:7922 -#, fuzzy, c-format +#, c-format msgid "" " Split compilation unit at offset %:\n" " Version: %, Abbreviation section offset: %, Address size: " "%, Offset size: %\n" msgstr "" -" Модуль компіляції за зміщенням %:\n" +" Модуль розділеної компіляції за зміщенням %:\n" " Версія: %, Зміщення розділу скорочень: %, Адреса: %, " "Зміщення: %\n" @@ -5449,9 +5458,9 @@ msgstr "" "\n" #: src/readelf.c:8306 -#, fuzzy, c-format +#, c-format msgid "unknown form: %s" -msgstr "невідома форма %#" +msgstr "невідома форма: %s" #: src/readelf.c:8337 #, c-format @@ -5460,7 +5469,7 @@ msgstr "не вдалося отримати дані розділу ліній #. Print what we got so far. #: src/readelf.c:8439 -#, fuzzy, c-format +#, c-format msgid "" "\n" " Length: %\n" @@ -5481,9 +5490,11 @@ msgstr "" " Довжина: %\n" " Версія DWARF: %\n" " Довжина вступу: %\n" +" Розмір адреси: %zd\n" +" Розмір селектора сегментів: %zd\n" " Мінімальна довж. інстр.: %\n" " Макс. к-ть операцій на інструкцію: %\n" -" Поч. значення, якщо «%s»: %\n" +" Поч. значення, якщо «is_stmt»: %\n" " Основа рядків: %\n" " Діапазон рядків: %\n" " Основа кодів операцій: %\n" @@ -5491,19 +5502,19 @@ msgstr "" "Коди операцій:\n" #: src/readelf.c:8461 -#, fuzzy, c-format +#, c-format msgid "cannot handle .debug_line version: %u\n" -msgstr "не вдалося отримати версію символу: %s" +msgstr "не вдалося обробити версію .debug_line: %u\n" #: src/readelf.c:8469 -#, fuzzy, c-format +#, c-format msgid "cannot handle address size: %u\n" -msgstr "непідтримуваний розмір адреси" +msgstr "не вдалося обробити розмір адреси: %u\n" #: src/readelf.c:8477 -#, fuzzy, c-format +#, c-format msgid "cannot handle segment selector size: %u\n" -msgstr "не вдалося отримати розділ: %s" +msgstr "не вдалося обробити розмір селектора сегментів: %u\n" #: src/readelf.c:8487 #, c-format @@ -5527,26 +5538,21 @@ msgstr "" "Таблиця каталогу:" #: src/readelf.c:8519 src/readelf.c:8596 -#, fuzzy, c-format +#, c-format msgid " [" -msgstr " PC: " +msgstr " [" #: src/readelf.c:8590 -#, fuzzy msgid "" "\n" "File name table:" msgstr "" "\n" -" Таблиця місця виклику:" +" Таблиця назв файлів:" #: src/readelf.c:8651 -#, fuzzy msgid " Entry Dir Time Size Name" -msgstr "" -"\n" -"Таблиця назв файлів:\n" -" Запис Кат Час Розмір Назва" +msgstr " Запис Кат Час Розмір Назва" #: src/readelf.c:8688 msgid "" @@ -5562,21 +5568,19 @@ msgid "invalid maximum operations per instruction is zero" msgstr "некоректну кількість операцій на інструкцію прирівняно до нуля" #: src/readelf.c:8745 -#, fuzzy, c-format +#, c-format msgid " special opcode %u: address+%u = " -msgstr " спеціальний код операції %u: адреса+%u = %s, рядок%+d = %zu\n" +msgstr " спеціальний код операції %u: адреса+%u = " #: src/readelf.c:8749 -#, fuzzy, c-format +#, c-format msgid ", op_index = %u, line%+d = %zu\n" -msgstr "" -" спеціальний код операції %u: адреса+%u = %s, індекс_оп = %u, рядок%+d = " -"%zu\n" +msgstr ", індекс_оп = %u, рядок%+d = %zu\n" #: src/readelf.c:8752 #, c-format msgid ", line%+d = %zu\n" -msgstr "" +msgstr ", рядок%+d = %zu\n" #: src/readelf.c:8770 #, c-format @@ -5588,9 +5592,9 @@ msgid " end of sequence" msgstr " кінець послідовності" #: src/readelf.c:8793 -#, fuzzy, c-format +#, c-format msgid " set address to " -msgstr " встановити адресу у значення %s\n" +msgstr " встановити адресу у значення " #: src/readelf.c:8821 #, c-format @@ -5615,14 +5619,14 @@ msgid " copy" msgstr " копія" #: src/readelf.c:8863 -#, fuzzy, c-format +#, c-format msgid " advance address by %u to " -msgstr " збільшення адреси на %u до %s\n" +msgstr " збільшення адреси на %u до " #: src/readelf.c:8867 src/readelf.c:8928 #, c-format msgid ", op_index to %u" -msgstr "" +msgstr ", op_index до %u" #: src/readelf.c:8879 #, c-format @@ -5650,14 +5654,14 @@ msgid " set basic block flag" msgstr " встановити прапорець базового блоку" #: src/readelf.c:8924 -#, fuzzy, c-format +#, c-format msgid " advance address by constant %u to " -msgstr " збільшити адресу на сталу величину %u до %s\n" +msgstr " збільшити адресу на сталу величину %u до " #: src/readelf.c:8944 -#, fuzzy, c-format +#, c-format msgid " advance address by fixed value %u to \n" -msgstr " збільшити адресу на фіксовану величину %u до %s\n" +msgstr " збільшити адресу на фіксовану величину %u до \n" #. Takes no argument. #: src/readelf.c:8954 @@ -5686,14 +5690,14 @@ msgstr[1] " невідомий код операції з % параме msgstr[2] " невідомий код операції з % параметрами:" #: src/readelf.c:9018 -#, fuzzy, c-format +#, c-format msgid "cannot get .debug_loclists content: %s" -msgstr "не вдалося отримати вміст .debug_loc: %s" +msgstr "не вдалося отримати вміст .debug_loclists: %s" #: src/readelf.c:9187 -#, fuzzy, c-format +#, c-format msgid "invalid loclists data" -msgstr "некоректні дані" +msgstr "некоректні дані loclists" #: src/readelf.c:9440 #, c-format @@ -5735,9 +5739,9 @@ msgid " unknown version, cannot parse section\n" msgstr " невідома версія, не вдалося обробити розділ\n" #: src/readelf.c:9931 -#, fuzzy, c-format +#, c-format msgid " Flag: 0x%" -msgstr " Прапорець: 0x%\n" +msgstr " Прапорець: 0x%" #: src/readelf.c:9960 #, c-format @@ -5787,38 +5791,34 @@ msgstr "" " %*s Рядок\n" #: src/readelf.c:10287 -#, fuzzy, c-format +#, c-format msgid " *** error, missing string terminator\n" -msgstr " *** помилка під час читання рядків: %s\n" +msgstr " *** помилка, пропущено роздільник рядків\n" #: src/readelf.c:10316 -#, fuzzy, c-format +#, c-format msgid "cannot get .debug_str_offsets section data: %s" -msgstr "не вдалося отримати дані розділу: %s" +msgstr "не вдалося отримати дані розділу .debug_str_offsets: %s" #: src/readelf.c:10415 -#, fuzzy, c-format +#, c-format msgid " Length: %8\n" -msgstr "" -"\n" -" Довжина: %6\n" +msgstr " Довжина: %8\n" #: src/readelf.c:10417 -#, fuzzy, c-format +#, c-format msgid " Offset size: %8\n" -msgstr " Довжина зміщення: %\n" +msgstr " Розмір зсуву: %8\n" #: src/readelf.c:10431 -#, fuzzy, c-format +#, c-format msgid " DWARF version: %8\n" -msgstr " версія DWARF: %6\n" +msgstr " версія DWARF: %8\n" #: src/readelf.c:10440 -#, fuzzy, c-format +#, c-format msgid " Padding: %8\n" -msgstr "" -"\n" -" Довжина: %6\n" +msgstr " Заповнення: %8\n" #: src/readelf.c:10494 #, c-format @@ -5984,9 +5984,9 @@ msgid " %-13.*s %9 %s\n" msgstr " %-13.*s %9 %s\n" #: src/readelf.c:12400 -#, fuzzy, c-format +#, c-format msgid "cannot get content of note: %s" -msgstr "не вдалося отримати вміст розділу записів: %s" +msgstr "не вдалося отримати вміст нотатки: %s" #: src/readelf.c:12434 #, c-format @@ -6031,14 +6031,15 @@ msgstr "" "Шіст. дамп розділу [%zu] «%s», % байтів за зміщенням %#0:\n" #: src/readelf.c:12541 -#, fuzzy, c-format +#, c-format msgid "" "\n" "Hex dump of section [%zu] '%s', % bytes (%zd uncompressed) at offset " "%#0:\n" msgstr "" "\n" -"Шіст. дамп розділу [%zu] «%s», % байтів за зміщенням %#0:\n" +"Шіст. дамп розділу [%zu] «%s», % байтів (%zd нестиснено) за " +"зміщенням %#0:\n" #: src/readelf.c:12555 #, c-format @@ -6059,14 +6060,15 @@ msgstr "" "Розділ рядків [%zu] «%s» містить % байтів за зміщенням %#0:\n" #: src/readelf.c:12592 -#, fuzzy, c-format +#, c-format msgid "" "\n" "String section [%zu] '%s' contains % bytes (%zd uncompressed) at " "offset %#0:\n" msgstr "" "\n" -"Розділ рядків [%zu] «%s» містить % байтів за зміщенням %#0:\n" +"Рядок розділу [%zu] «%s» містить % байти (%zd нестиснено) на " +"зміщенні %#0:\n" #: src/readelf.c:12641 #, c-format @@ -6187,9 +6189,9 @@ msgid " (ex %s)" msgstr " (прикл. %s)" #: src/size.c:482 -#, fuzzy, c-format +#, c-format msgid "cannot get section header" -msgstr "не вдалося отримати заголовок розділу\n" +msgstr "не вдалося отримати заголовок розділу" #: src/size.c:582 msgid "(TOTALS)\n" @@ -6305,7 +6307,6 @@ msgstr "" "файлами діагностичних даних" #: src/stack.c:680 -#, fuzzy msgid "" "Print a stack for each thread in a process or core file.\n" "\n" @@ -6381,9 +6382,9 @@ msgid "invalid minimum length of matched string size" msgstr "некоректна мінімальна довжина розмірності рядка для порівняння" #: src/strings.c:585 -#, fuzzy, c-format +#, c-format msgid "lseek failed" -msgstr "помилка lseek64" +msgstr "помилка lseek" #: src/strings.c:602 src/strings.c:666 #, c-format @@ -6441,6 +6442,10 @@ msgid "" "is not reversable, incompatible with -f, -g, --remove-comment and --remove-" "section)" msgstr "" +"Подібний до --reloc-debug-sections, або усі тривіальні переміщення між " +"розділами діагностики вирішуються на місці. Додаткове очищення не " +"виконується (дію неможливо скасувати, параметр несумісний із -f, -g, --" +"remove-comment та --remove-section)" #: src/strip.c:89 msgid "Remove .comment section" @@ -6451,12 +6456,17 @@ msgid "" "Remove the named section. SECTION is an extended wildcard pattern. May be " "given more than once. Only non-allocated sections can be removed." msgstr "" +"Вилучити іменований розділ. РОЗДІЛ є розширеним взірцем із символами-" +"замінниками. Можна вказувати декілька розділів. Може бути вилучено лише " +"нерозміщені у пам'яті розділи." #: src/strip.c:91 msgid "" "Keep the named section. SECTION is an extended wildcard pattern. May be " "given more than once." msgstr "" +"Зберегти іменований розділ. РОЗДІЛ є розширеним взірцем із символами-" +"замінниками. Можна вказувати декілька розділів." #. Short description of program. #: src/strip.c:98 @@ -6474,6 +6484,8 @@ msgid "" "--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --" "remove-section" msgstr "" +"--reloc-debug-sections-only є несумісним із -f, -g, --remove-comment та --" +"remove-section" #: src/strip.c:267 #, c-format @@ -6492,9 +6504,9 @@ msgid "-F option specified twice" msgstr "параметр -F вказано двічі" #: src/strip.c:362 -#, fuzzy, c-format +#, c-format msgid "cannot both keep and remove .comment section" -msgstr "Вилучити розділ .comment" +msgstr "неможливо одночасно зберегти і вилучити розділ .comment" #: src/strip.c:574 #, c-format @@ -6540,14 +6552,14 @@ msgid "cannot get number of phdrs" msgstr "не вдалося отримати кількість phdr" #: src/strip.c:1060 src/strip.c:1103 -#, fuzzy, c-format +#, c-format msgid "cannot create new ehdr for file '%s': %s" -msgstr "не вдалося створити файл «%s»: %s" +msgstr "не вдалося створити ehdr для файла «%s»: %s" #: src/strip.c:1070 src/strip.c:1113 -#, fuzzy, c-format +#, c-format msgid "cannot create new phdr for file '%s': %s" -msgstr "не вдалося створити файл «%s»: %s" +msgstr "не вдалося створити phdr для файла «%s»: %s" #: src/strip.c:1194 #, c-format @@ -6555,14 +6567,14 @@ msgid "illformed file '%s'" msgstr "помилкове форматування файла «%s»" #: src/strip.c:1204 -#, fuzzy, c-format +#, c-format msgid "Cannot remove allocated section '%s'" -msgstr "не вдалося розмістити PLT-розділ: %s" +msgstr "Неможливо вилучити розміщений у пам'яті розділ «%s»" #: src/strip.c:1213 -#, fuzzy, c-format +#, c-format msgid "Cannot both keep and remove section '%s'" -msgstr "не вдалося додати новий розділ: %s" +msgstr "Неможливо одночасно зберегти та вилучити розділ «%s»" #: src/strip.c:1573 src/strip.c:1688 #, c-format @@ -6570,19 +6582,19 @@ msgid "while generating output file: %s" msgstr "під час спроби створення файла з виведеними даними: %s" #: src/strip.c:1637 -#, fuzzy, c-format +#, c-format msgid "%s: error while updating ELF header: %s" -msgstr "%s: помилка під час створення заголовка ELF: %s" +msgstr "%s: помилка під час оновлення заголовка ELF: %s" #: src/strip.c:1646 -#, fuzzy, c-format +#, c-format msgid "%s: error while getting shdrstrndx: %s" -msgstr "%s: помилка під час створення заголовка ELF: %s" +msgstr "%s: помилка під час отримання shdrstrndx: %s" #: src/strip.c:1654 src/strip.c:2535 -#, fuzzy, c-format +#, c-format msgid "%s: error updating shdrstrndx: %s" -msgstr "%s: помилка під час створення заголовка ELF: %s" +msgstr "%s: помилка під час оновлення shdrstrndx: %s" #: src/strip.c:1671 #, c-format @@ -6605,14 +6617,15 @@ msgid "while create section header string table: %s" msgstr "під час створення таблиці рядків заголовка розділу: %s" #: src/strip.c:1815 -#, fuzzy, c-format +#, c-format msgid "no memory to create section header string table" -msgstr "під час створення таблиці рядків заголовка розділу: %s" +msgstr "недостатньо пам'яті для створення таблиці рядків заголовка розділу" #: src/strip.c:2028 #, c-format msgid "Cannot remove symbol [%zd] from allocated symbol table [%zd]" msgstr "" +"Неможливо вилучити символ [%zd] з розміщеної у пам'яті таблиці символів [%zd]" #: src/strip.c:2451 src/strip.c:2559 #, c-format @@ -6738,9 +6751,9 @@ msgid "cannot create ELF header: %s" msgstr "не вдалося створити заголовок ELF: %s" #: src/unstrip.c:244 -#, fuzzy, c-format +#, c-format msgid "cannot get shdrstrndx:%s" -msgstr "не вдалося отримати розділ: %s" +msgstr "не вдалося отримати shdrstrndx:%s" #: src/unstrip.c:248 src/unstrip.c:2081 #, c-format @@ -6748,14 +6761,14 @@ msgid "cannot get ELF header: %s" msgstr "не вдалося отримати заголовок ELF: %s" #: src/unstrip.c:258 -#, fuzzy, c-format +#, c-format msgid "cannot get new zero section: %s" -msgstr "не вдалося отримати розділ: %s" +msgstr "не вдалося отримати новий нульовий розділ: %s" #: src/unstrip.c:261 -#, fuzzy, c-format +#, c-format msgid "cannot update new zero section: %s" -msgstr "не вдалося оновити пересування: %s" +msgstr "неможливо оновити новий нульовий розділ: %s" #: src/unstrip.c:265 #, c-format @@ -6830,14 +6843,14 @@ msgid "unexpected section type in [%zu] with sh_link to symtab" msgstr "неочікуваний тип розділу у [%zu] з посиланням sh_link на symtab" #: src/unstrip.c:842 -#, fuzzy, c-format +#, c-format msgid "cannot get symbol section data: %s" -msgstr "не вдалося отримати дані розділу: %s" +msgstr "не вдалося отримати дані розділу символів: %s" #: src/unstrip.c:844 -#, fuzzy, c-format +#, c-format msgid "cannot get string section data: %s" -msgstr "не вдалося отримати дані розділу: %s" +msgstr "не вдалося отримати дані розділу рядків: %s" #: src/unstrip.c:861 #, c-format @@ -6850,29 +6863,29 @@ msgid "cannot read section [%zu] name: %s" msgstr "не вдалося прочитати назву розділу [%zu]: %s" #: src/unstrip.c:1034 -#, fuzzy, c-format +#, c-format msgid "bad sh_link for group section: %s" -msgstr "некоректне значення sh_link у розділі %zu" +msgstr "помилкове значення sh_link для розділу груп: %s" #: src/unstrip.c:1040 -#, fuzzy, c-format +#, c-format msgid "couldn't get shdr for group section: %s" -msgstr "не вдалося отримати заголовок 0-го розділу: %s" +msgstr "не вдалося отримати shdr для розділу груп: %s" #: src/unstrip.c:1045 -#, fuzzy, c-format +#, c-format msgid "bad data for group symbol section: %s" -msgstr "не вдалося отримати дані для розділу символів\n" +msgstr "помилкові дані для розділу символів груп: %s" #: src/unstrip.c:1051 -#, fuzzy, c-format +#, c-format msgid "couldn't get symbol for group section: %s" -msgstr "не вдалося отримати версію символу: %s" +msgstr "не вдалося отримати символ для розділу груп: %s" #: src/unstrip.c:1056 -#, fuzzy, c-format +#, c-format msgid "bad symbol name for group section: %s" -msgstr "не вдалося отримати заголовок розділу %zu: %s" +msgstr "помилкова назва символу для розділу груп: %s" #: src/unstrip.c:1098 src/unstrip.c:1117 src/unstrip.c:1155 #, c-format @@ -6882,7 +6895,7 @@ msgstr "не вдалося прочитати розділ «.gnu.prelink_undo #: src/unstrip.c:1135 #, c-format msgid "overflow with shnum = %zu in '%s' section" -msgstr "" +msgstr "переповнення з shnum = %zu у розділі «%s»" #: src/unstrip.c:1146 #, c-format @@ -6925,7 +6938,7 @@ msgstr "" #: src/unstrip.c:1400 #, c-format msgid "no sections in stripped file" -msgstr "" +msgstr "у очищеному файлі немає розділів" #: src/unstrip.c:1471 src/unstrip.c:1564 #, c-format @@ -6943,9 +6956,9 @@ msgid "symbol [%zu] has invalid section index" msgstr "символ [%zu] має некоректний індекс розділу" #: src/unstrip.c:1785 -#, fuzzy, c-format +#, c-format msgid "group has invalid section index [%zd]" -msgstr "символ [%zu] має некоректний індекс розділу" +msgstr "група містить некоректний індекс розділу [%zd]" #: src/unstrip.c:2060 #, c-format @@ -7060,7 +7073,6 @@ msgstr "" "[МОДУЛЬ...]" #: src/unstrip.c:2551 -#, fuzzy msgid "" "Combine stripped files with separate symbols and debug information.\n" "\n" diff --git a/libdrgn/elfutils/src/ChangeLog b/libdrgn/elfutils/src/ChangeLog index e11fe79a5..83d586071 100644 --- a/libdrgn/elfutils/src/ChangeLog +++ b/libdrgn/elfutils/src/ChangeLog @@ -1,3 +1,12 @@ +2020-04-17 Mark Wielaard + + * readelf.c (print_debug): Check .gnu.debuglto_ prefix. + +2020-04-16 Mark Wielaard + + * elflint.c (check_sections): Mask out SHF_EXCLUDE from processor + specific section flags when --gnu is given. + 2020-02-08 Mark Wielaard * elflint.c (check_program_header): Handle PT_GNU_PROPERTY. diff --git a/libdrgn/elfutils/src/elflint.c b/libdrgn/elfutils/src/elflint.c index 480d84ba9..0ef432366 100644 --- a/libdrgn/elfutils/src/elflint.c +++ b/libdrgn/elfutils/src/elflint.c @@ -3921,6 +3921,11 @@ section [%2zu] '%s': size not multiple of entry size\n"), GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS; if (sh_flags & SHF_MASKPROC) { + /* Strictly speaking SHF_EXCLUDE is a processor specific + section flag, but it is used generically in the GNU + toolchain. */ + if (gnuld) + sh_flags &= ~(GElf_Xword) SHF_EXCLUDE; if (!ebl_machine_section_flag_check (ebl, sh_flags & SHF_MASKPROC)) ERROR (gettext ("section [%2zu] '%s'" diff --git a/libdrgn/elfutils/src/readelf.c b/libdrgn/elfutils/src/readelf.c index cbb519d18..685d0b177 100644 --- a/libdrgn/elfutils/src/readelf.c +++ b/libdrgn/elfutils/src/readelf.c @@ -11253,7 +11253,8 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) if (strcmp (name, ".debug_info") == 0 || strcmp (name, ".debug_info.dwo") == 0 || strcmp (name, ".zdebug_info") == 0 - || strcmp (name, ".zdebug_info.dwo") == 0) + || strcmp (name, ".zdebug_info.dwo") == 0 + || strcmp (name, ".gnu.debuglto_.debug_info") == 0) { print_debug_info_section (dwflmod, ebl, ehdr, scn, shdr, dbg); @@ -11339,7 +11340,11 @@ print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr) dbglen - 1) == 0 && (scnlen == dbglen + 1 || (scnlen == dbglen + 5 - && strstr (name, ".dwo") == name + dbglen + 1)))) + && strstr (name, ".dwo") == name + dbglen + 1))) + || (scnlen > 14 /* .gnu.debuglto_ prefix. */ + && strncmp (name, ".gnu.debuglto_", 14) == 0 + && strcmp (&name[14], debug_sections[n].name) == 0) +) { if ((print_debug_sections | implicit_debug_sections) & debug_sections[n].bitmask) diff --git a/libdrgn/elfutils/tests/ChangeLog b/libdrgn/elfutils/tests/ChangeLog index 01e4a0830..4e9ae020b 100644 --- a/libdrgn/elfutils/tests/ChangeLog +++ b/libdrgn/elfutils/tests/ChangeLog @@ -1,3 +1,115 @@ +2020-05-05 Mark Wielaard + + * testfile-lto-gcc8.bz2: New test file. + * testfile-lto-gcc9.bz2: Likewise. + * Makefile.am (EXTRA_DIST): Add testfile-lto-gcc8.bz2 and + testfile-lto-gcc9.bz2. + * run-allfcts.sh: Add testfile-lto-gcc9 and testfile-lto-gcc8 + tests. + +2020-05-05 Mark Wielaard + + * testfile-lto-gcc10.bz2: New test file. + * Makefile.am (EXTRA_DIST): Add testfile-lto-gcc10.bz2. + * run-allfcts.sh: Add testfile-lto-gcc10 test. + +2020-04-17 Mark Wielaard + + * test-subr.sh (testrun_on_self_obj): New function. + * run-varlocs-self.sh: Run testrun_on_self_exe and + testrun_on_self_lib with -e, run testrun_on_self_obj with + --exprlocs -e. + +2020-04-17 Mark Wielaard + + * Makefile.am (test-nlist$): New goal with minimal CFLAGS. + (test_nlist_CFLAGS): New variable. + +2020-03-28 Frank Ch. Eigler + + * run-debuginfod-find.sh: Test timestamps of archive-origin files. + +2020-03-27 Frank Ch. Eigler + + * run-debuginfod-find.sh: Test /path/-based debuginfod-find. + +2020-03-24 Frank Ch. Eigler + + * run-debuginfod-find.sh: Test relay of UA and XFF headers across + federating debuginfods. + +2020-03-26 Frank Ch. Eigler + + * run-debuginfod-find.sh: Look for debuginfod's new + http_responses_* metrics. + +2020-03-26 Frank Ch. Eigler + + * run-debuginfod-find.sh: Look for bsdtar instead of dpkg. + +2020-03-26 Frank Ch. Eigler + + * run-debuginfod-find.sh: Check for bsdtar zstd capability + for running tests against zstd-compressed fedora31 rpms. + +2020-03-26 Mark Wielaard + + * Makefile.am (EXTRA_DIST): Add + debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm, + debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm, + debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm, + debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm, + debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm, + debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm + +2020-03-24 Frank Ch. Eigler + + * debuginfod-rpms/hello3.spec., /fedora31/*: New files with + uncanonicalized source paths. + * run-debuginfod-find.sh: Test them. + +2020-03-24 Frank Ch. Eigler + + * run-debuginfod-find.sh: Test the more detailed debuginfod + webapi log format. + +2020-03-23 Mark Wielaard + + * getphdrnum.c: Include config.h. + * run-lfs-symbols.sh: Also check that file exists. Add more logs. + Remove ebl modules check. + +2020-03-22 Omar Sandoval + Mark Wielaard + + * getphdrnum.c: New file. + * run-getphdrnum.sh: New test. + * testfile-phdrs.elf.bz2: New test file. + * Makefile.am (check_PROGRAMS): Add getphdrnum. + (TESTS): Add run-getphdrnum.sh. + (EXTRA_DIST): Add run-getphdrnum.sh and testfile-phdrs.elf.bz2. + (getphdrnum_LDADD): New variable. + +2020-03-22 Frank Ch. Eigler + + * run-debuginfod-find.sh: Look for URL in default progressfn + and from debuginfod-find -v. + +2020-02-19 Aaron Merey + + * run-debuginfod-find.sh: Run tests for verifying default + client cache locations. + +2020-02-26 Konrad Kleine + + * run-debuginfod-find.sh: added tests for DEBUGINFOD_URLS beginning + with "file://" + +2020-02-21 Mark Wielaard + + * Makefile.am (TESTS_ENVIRONMENT): Explicitly unset DEBUGINFOD_URLS. + (installed_TESTS_ENVIRONMENT): Likewise. + 2020-02-19 Aaron Merey * run-debuginfod-find.sh: Test that files unrelated to debuginfod diff --git a/libdrgn/elfutils/tests/Makefile.am b/libdrgn/elfutils/tests/Makefile.am index 1db1150df..a7ad07d0d 100644 --- a/libdrgn/elfutils/tests/Makefile.am +++ b/libdrgn/elfutils/tests/Makefile.am @@ -62,7 +62,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ get-units-invalid get-units-split attr-integrate-skel \ all-dwarf-ranges unit-info next_cfi \ elfcopy addsections xlate_notes elfrdwrnop \ - dwelf_elf_e_machine_string + dwelf_elf_e_machine_string \ + getphdrnum asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -79,6 +80,14 @@ backtrace-child-biarch$(EXEEXT): backtrace-child.c $(AM_LDFLAGS) $(LDFLAGS) $(backtrace_child_LDFLAGS) \ -o $@ $< +# test_nlist checks its own symbol table, and expects various symbols +# to be in the order as specified in the source file. Explicitly set +# minimal CFLAGS +test-nlist$(EXEEXT): test-nlist.c + $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ + $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(test_nlist_CFLAGS) $(test_nlist_LDADD) -o $@ $< + TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ update1 update2 update3 update4 \ run-show-die-info.sh run-get-files.sh run-get-lines.sh \ @@ -168,7 +177,8 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-dwelf_elf_e_machine_string.sh \ run-elfclassify.sh run-elfclassify-self.sh \ run-disasm-riscv64.sh \ - run-pt_gnu_prop-tests.sh + run-pt_gnu_prop-tests.sh \ + run-getphdrnum.sh if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -208,6 +218,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ testfile9.bz2 testfile10.bz2 testfile11.bz2 testfile12.bz2 \ testfile13.bz2 run-strip-test3.sh run-allfcts.sh \ testfile_class_func.bz2 testfile_nested_funcs.bz2 \ + testfile-lto-gcc10.bz2 \ + testfile-lto-gcc9.bz2 testfile-lto-gcc8.bz2 \ run-line2addr.sh run-elflint-test.sh testfile14.bz2 \ run-strip-test4.sh run-strip-test5.sh run-strip-test6.sh \ run-strip-test7.sh run-strip-test8.sh run-strip-groups.sh \ @@ -455,6 +467,12 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ debuginfod-rpms/fedora30/hello2-debugsource-1.0-2.x86_64.rpm \ debuginfod-rpms/fedora30/hello2-two-1.0-2.x86_64.rpm \ debuginfod-rpms/fedora30/hello2-two-debuginfo-1.0-2.x86_64.rpm \ + debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm \ + debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm \ + debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm \ + debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm \ + debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm \ + debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm \ debuginfod-rpms/hello2.spec. \ debuginfod-rpms/rhel6/hello2-1.0-2.i686.rpm \ debuginfod-rpms/rhel6/hello2-1.0-2.src.rpm \ @@ -476,7 +494,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ debuginfod-tars/pacman-sources/README.md \ debuginfod-tars/pacman-sources/hello.c \ run-pt_gnu_prop-tests.sh \ - testfile_pt_gnu_prop.bz2 testfile_pt_gnu_prop32.bz2 + testfile_pt_gnu_prop.bz2 testfile_pt_gnu_prop32.bz2 \ + run-getphdrnum.sh testfile-phdrs.elf.bz2 if USE_VALGRIND @@ -495,6 +514,7 @@ installed_TESTS_ENVIRONMENT = libdir=$(DESTDIR)$(libdir); \ export abs_top_builddir; \ export libdir; export bindir; \ export LC_ALL; export LANG; export VALGRIND_CMD; \ + unset DEBUGINFOD_URLS; \ NM=$(NM); export NM; installed_LOG_COMPILER = $(abs_srcdir)/test-wrapper.sh \ installed $(tests_rpath) \ @@ -509,6 +529,7 @@ TESTS_ENVIRONMENT = LC_ALL=C; LANG=C; VALGRIND_CMD=$(valgrind_cmd); \ export abs_srcdir; export abs_builddir; \ export abs_top_builddir; \ export LC_ALL; export LANG; export VALGRIND_CMD; \ + unset DEBUGINFOD_URLS; \ NM=$(NM); export NM; LOG_COMPILER = $(abs_srcdir)/test-wrapper.sh \ $(abs_top_builddir)/libdw:$(abs_top_builddir)/backends:$(abs_top_builddir)/libelf:$(abs_top_builddir)/libasm:$(abs_top_builddir)/debuginfod @@ -546,6 +567,7 @@ scnnames_LDADD = $(libelf) sectiondump_LDADD = $(libelf) showptable_LDADD = $(libelf) hash_LDADD = $(libelf) +test_nlist_CFLAGS =-g -O0 test_nlist_LDADD = $(libelf) msg_tst_LDADD = $(libelf) newscn_LDADD = $(libelf) @@ -652,6 +674,7 @@ debuginfod_build_id_find_LDADD = $(libelf) $(libdw) xlate_notes_LDADD = $(libelf) elfrdwrnop_LDADD = $(libelf) dwelf_elf_e_machine_string_LDADD = $(libelf) $(libdw) +getphdrnum_LDADD = $(libelf) $(libdw) # We want to test the libelf header against the system elf.h header. # Don't include any -I CPPFLAGS. Except when we install our own elf.h. diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm new file mode 100644 index 000000000..d0b345408 Binary files /dev/null and b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm differ diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm new file mode 100644 index 000000000..8b2fe9bbd Binary files /dev/null and b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm differ diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm new file mode 100644 index 000000000..ee479ecb4 Binary files /dev/null and b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm differ diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm new file mode 100644 index 000000000..890478e42 Binary files /dev/null and b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm differ diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm new file mode 100644 index 000000000..73fd939d1 Binary files /dev/null and b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm differ diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm new file mode 100644 index 000000000..0cc24073a Binary files /dev/null and b/libdrgn/elfutils/tests/debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm differ diff --git a/libdrgn/elfutils/tests/debuginfod-rpms/hello3.spec. b/libdrgn/elfutils/tests/debuginfod-rpms/hello3.spec. new file mode 100644 index 000000000..ffb95134e --- /dev/null +++ b/libdrgn/elfutils/tests/debuginfod-rpms/hello3.spec. @@ -0,0 +1,60 @@ +Summary: hello3 -- double hello, world rpm +Name: hello3 +Version: 1.0 +Release: 2 +Group: Utilities +License: GPL +Distribution: RPM ^W Elfutils test suite. +Vendor: Red Hat Software +Packager: Red Hat Software +URL: http://www.redhat.com +BuildRequires: gcc make +Source0: hello-1.0.tar.gz + +%description +Simple rpm demonstration with an eye to consumption by debuginfod. + +%package two +Summary: hello3two +License: GPL + +%description two +Dittoish. + +%prep +%setup -q -n hello-1.0 + +%build +mkdir foobar +gcc -g -O1 foobar///./../hello.c -o hello +gcc -g -O2 -D_FORTIFY_SOURCE=2 foobar///./../hello.c -o hello3 + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT/usr/local/bin +cp hello $RPM_BUILD_ROOT/usr/local/bin/ +cp hello3 $RPM_BUILD_ROOT/usr/local/bin/ + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%attr(0751,root,root) /usr/local/bin/hello + +%files two +%defattr(-,root,root) +%attr(0751,root,root) /usr/local/bin/hello3 + +%changelog +* Tue Mar 24 2020 Frank Ch. Eigler +- New variant of hello2, with crazy source file paths + +* Thu Nov 14 2019 Frank Ch. Eigler +- Dropped misc files not relevant to debuginfod testing. + +* Wed May 18 2016 Mark Wielaard +- Add hello2 for dwz testing support. + +* Tue Oct 20 1998 Jeff Johnson +- create. diff --git a/libdrgn/elfutils/tests/getphdrnum.c b/libdrgn/elfutils/tests/getphdrnum.c new file mode 100644 index 000000000..07f75db0b --- /dev/null +++ b/libdrgn/elfutils/tests/getphdrnum.c @@ -0,0 +1,48 @@ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include + +int main (int argc, const char **argv) +{ + int fd; + Elf *elf; + size_t phnum; + + if (argc != 2) + { + fprintf (stderr, "usage: %s FILE\n", argv[0]); + return EXIT_FAILURE; + } + + fd = open (argv[1], O_RDONLY); + if (fd == -1) + { + perror ("open"); + return EXIT_FAILURE; + } + elf_version (EV_CURRENT); + elf = elf_begin (fd, ELF_C_READ, NULL); + if (!elf) + { + fprintf (stderr, "elf_begin: %s\n", elf_errmsg (-1)); + return EXIT_FAILURE; + } + if (elf_getphdrnum (elf, &phnum)) + { + fprintf(stderr, "elf_getphdrnum: %s\n", elf_errmsg (-1)); + return EXIT_FAILURE; + } + + printf("%zu\n", phnum); + + elf_end (elf); + close (fd); + + return EXIT_SUCCESS; +} diff --git a/libdrgn/elfutils/tests/run-allfcts.sh b/libdrgn/elfutils/tests/run-allfcts.sh index 6eaf13c8b..9c0a55d86 100755 --- a/libdrgn/elfutils/tests/run-allfcts.sh +++ b/libdrgn/elfutils/tests/run-allfcts.sh @@ -91,4 +91,83 @@ testrun_compare ${abs_builddir}/allfcts testfile_nested_funcs testfile_class_fun /home/mark/src/tests/nested/class_func.cxx:13:main EOF +# = testfile-lto.h = +# struct t +# { +# int *p; +# int c; +# }; +# +# extern int foo (int i, struct t *t); + +# = testfile-lto-func.c = +# #include "testfile-lto.h" +# +# int +# foo (int i, struct t *t) +# { +# int j, res = 0; +# for (j = 0; j < i && j < t->c; j++) +# res += t->p[j]; +# +# return res; +# } + +# = testfile-lto-main.c = +# #include "testfile-lto.h" +# +# static struct t g; +# +# int +# main (int argc, char **argv) +# { +# int i; +# int j[argc]; +# g.c = argc; +# g.p = j; +# for (i = 0; i < argc; i++) +# j[i] = (int) argv[i][0]; +# return foo (3, &g); +# } + +# Using gcc (GCC) 10.0.1 20200430 (Red Hat 10.0.1-0.13) +# gcc -g -O2 -flto -c testfile-lto-func.c +# gcc -g -O2 -flto -c testfile-lto-main.c +# gcc -g -O2 -flto -o testfile-lto-gcc10 testfile-lto-func.o testfile-lto-main.o + +testfiles testfile-lto-gcc10 + +testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc10 <<\EOF +/home/mark/src/tests/testfile-lto-main.c:6:main +/home/mark/src/tests/testfile-lto-func.c:4:foo +/home/mark/src/tests/testfile-lto-main.c:6:main +EOF + +# Using gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3) +# gcc -g -O2 -flto -c testfile-lto-func.c +# gcc -g -O2 -flto -c testfile-lto-main.c +# gcc -g -O2 -flto -o testfile-lto-gcc8 testfile-lto-func.o testfile-lto-main.o + +testfiles testfile-lto-gcc8 + +testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc8 <<\EOF +/home/mark/src/tests/testfile-lto-func.c:4:foo +/home/mark/src/tests/testfile-lto-main.c:6:main +/home/mark/src/tests/testfile-lto-main.c:6:main +/home/mark/src/tests/testfile-lto-func.c:4:foo +EOF + +# gcc (GCC) 9.1.1 20190605 (Red Hat 9.1.1-2) +# gcc -g -O2 -flto -c testfile-lto-func.c +# gcc -g -O2 -flto -c testfile-lto-main.c +# gcc -g -O2 -flto -o testfile-lto-gcc9 testfile-lto-func.o testfile-lto-main.o + +testfiles testfile-lto-gcc9 + +testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc9 <<\EOF +/home/mark/src/tests/testfile-lto-main.c:6:main +/home/mark/src/tests/testfile-lto-func.c:4:foo +/home/mark/src/tests/testfile-lto-main.c:6:main +EOF + exit 0 diff --git a/libdrgn/elfutils/tests/run-debuginfod-find.sh b/libdrgn/elfutils/tests/run-debuginfod-find.sh index 2964e7c07..7faad3317 100755 --- a/libdrgn/elfutils/tests/run-debuginfod-find.sh +++ b/libdrgn/elfutils/tests/run-debuginfod-find.sh @@ -21,10 +21,12 @@ type curl 2>/dev/null || (echo "need curl"; exit 77) type rpm2cpio 2>/dev/null || (echo "need rpm2cpio"; exit 77) type bzcat 2>/dev/null || (echo "need bzcat"; exit 77) +bsdtar --version | grep -q zstd && zstd=true || zstd=false +echo "zstd=$zstd bsdtar=`bsdtar --version`" # for test case debugging, uncomment: -# set -x -# VERBOSE=-vvvv +#set -x +#VERBOSE=-vvvv DB=${PWD}/.debuginfod_tmp.sqlite tempfiles $DB @@ -40,7 +42,7 @@ cleanup() if [ $PID2 -ne 0 ]; then kill $PID2; wait $PID2; fi if [ $PID3 -ne 0 ]; then kill $PID3; wait $PID3; fi - rm -rf F R D L Z ${PWD}/.client_cache* + rm -rf F R D L Z ${PWD}/foobar ${PWD}/mocktree ${PWD}/.client_cache* ${PWD}/tmp* exit_cleanup } @@ -93,8 +95,9 @@ wait_ready() fi } -env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -R -d $DB -p $PORT1 -t0 -g0 --fdcache-fds 1 --fdcache-mbs 2 -Z .tar.xz -Z .tar.bz2=bzcat R F Z L & +env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -R -d $DB -p $PORT1 -t0 -g0 --fdcache-fds 1 --fdcache-mbs 2 -Z .tar.xz -Z .tar.bz2=bzcat -v R F Z L > vlog4 2>&1 & PID1=$! +tempfiles vlog4 # Server must become ready wait_ready $PORT1 'ready' 1 export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/ # or without trailing / @@ -112,7 +115,9 @@ export DEBUGINFOD_TIMEOUT=10 # cannot find it without debuginfod. echo "int main() { return 0; }" > ${PWD}/prog.c tempfiles prog.c -gcc -Wl,--build-id -g -o prog ${PWD}/prog.c +# Create a subdirectory to confound source path names +mkdir foobar +gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \ -a prog | grep 'Build ID' | cut -d ' ' -f 7` @@ -139,12 +144,62 @@ rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID` cmp $filename F/prog.debug -filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID` +filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable F/prog` cmp $filename F/prog +# raw source filename +filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID ${PWD}/foobar///./../prog.c` +cmp $filename ${PWD}/prog.c + +# and also the canonicalized one filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID ${PWD}/prog.c` cmp $filename ${PWD}/prog.c + +######################################################################## + +# Test whether the cache default locations are correct + +mkdir tmphome + +# $HOME/.cache should be created. +testrun env HOME=$PWD/tmphome XDG_CACHE_HOME= DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID +if [ ! -f $PWD/tmphome/.cache/debuginfod_client/$BUILDID/debuginfo ]; then + echo "could not find cache in $PWD/tmphome/.cache" + exit 1 +fi + +# $HOME/.cache should be found. +testrun env HOME=$PWD/tmphome XDG_CACHE_HOME= DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID +if [ ! -f $PWD/tmphome/.cache/debuginfod_client/$BUILDID/executable ]; then + echo "could not find cache in $PWD/tmphome/.cache" + exit 1 +fi + +# $XDG_CACHE_HOME should take priority over $HOME.cache. +testrun env HOME=$PWD/tmphome XDG_CACHE_HOME=$PWD/tmpxdg DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID +if [ ! -f $PWD/tmpxdg/debuginfod_client/$BUILDID/debuginfo ]; then + echo "could not find cache in $PWD/tmpxdg/" + exit 1 +fi + +# A cache at the old default location ($HOME/.debuginfod_client_cache) should take +# priority over $HOME/.cache, $XDG_CACHE_HOME. +cp -r $DEBUGINFOD_CACHE_PATH tmphome/.debuginfod_client_cache + +# Add a file that doesn't exist in $HOME/.cache, $XDG_CACHE_HOME. +mkdir tmphome/.debuginfod_client_cache/deadbeef +echo ELF... > tmphome/.debuginfod_client_cache/deadbeef/debuginfo +filename=`testrun env HOME=$PWD/tmphome XDG_CACHE_HOME=$PWD/tmpxdg DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo deadbeef` +cmp $filename tmphome/.debuginfod_client_cache/deadbeef/debuginfo + +# $DEBUGINFO_CACHE_PATH should take priority over all else. +testrun env HOME=$PWD/tmphome XDG_CACHE_HOME=$PWD/tmpxdg DEBUGINFOD_CACHE_PATH=$PWD/tmpcache ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID +if [ ! -f $PWD/tmpcache/$BUILDID/debuginfo ]; then + echo "could not find cache in $PWD/tmpcache/" + exit 1 +fi + ######################################################################## # Add artifacts to the search paths and test whether debuginfod finds them while already running. @@ -168,16 +223,21 @@ filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo $B cmp $filename F/prog2 cat vlog grep -q Progress vlog +grep -q Downloaded.from vlog tempfiles vlog filename=`testrun env DEBUGINFOD_PROGRESS=1 ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID2 2>vlog2` cmp $filename F/prog2 cat vlog2 -grep -q Downloading vlog2 +grep -q 'Downloading.*http' vlog2 tempfiles vlog2 filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID2 ${PWD}/prog2.c` cmp $filename ${PWD}/prog2.c cp -rvp ${abs_srcdir}/debuginfod-rpms R +if [ "$zstd" = "false" ]; then # nuke the zstd fedora 31 ones + rm -vrf R/debuginfod-rpms/fedora31 +fi + cp -rvp ${abs_srcdir}/debuginfod-tars Z kill -USR1 $PID1 # All rpms need to be in the index @@ -224,28 +284,40 @@ archive_test() { buildid=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \ -a $filename | grep 'Build ID' | cut -d ' ' -f 7` test $__BUILDID = $buildid + # check that timestamps are plausible - older than the near-present (tmpdir mtime) + test $filename -ot `pwd` # run again to assure that fdcache is being enjoyed filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $__BUILDID` buildid=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \ -a $filename | grep 'Build ID' | cut -d ' ' -f 7` test $__BUILDID = $buildid + test $filename -ot `pwd` filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $__BUILDID` buildid=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \ -a $filename | grep 'Build ID' | cut -d ' ' -f 7` test $__BUILDID = $buildid + test $filename -ot `pwd` if test "x$__SOURCEPATH" != "x"; then filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $__BUILDID $__SOURCEPATH` hash=`cat $filename | sha1sum | awk '{print $1}'` test $__SOURCESHA1 = $hash + test $filename -ot `pwd` fi } # common source file sha1 SHA=f4a1a8062be998ae93b8f1cd744a398c6de6dbb1 +# fedora31 +if [ $zstd = true ]; then + # fedora31 uses zstd compression on rpms, older rpm2cpio/libarchive can't handle it + # and we're not using the fancy -Z '.rpm=(rpm2cpio|zstdcat)<' workaround in this testsuite + archive_test 420e9e3308971f4b817cc5bf83928b41a6909d88 /usr/src/debug/hello3-1.0-2.x86_64/foobar////./../hello.c $SHA + archive_test 87c08d12c78174f1082b7c888b3238219b0eb265 /usr/src/debug/hello3-1.0-2.x86_64///foobar/./..//hello.c $SHA +fi # fedora30 archive_test c36708a78618d597dee15d0dc989f093ca5f9120 /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA archive_test 41a236eb667c362a1c4196018cc4581e09722b1b /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA @@ -293,8 +365,9 @@ export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache2 mkdir -p $DEBUGINFOD_CACHE_PATH # NB: inherits the DEBUGINFOD_URLS to the first server # NB: run in -L symlink-following mode for the L subdir -env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -U -d ${DB}_2 -p $PORT2 -L L D & +env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -U -d ${DB}_2 -p $PORT2 -L L D > vlog3 2>&1 & PID2=$! +tempfiles vlog3 tempfiles ${DB}_2 wait_ready $PORT2 'ready' 1 wait_ready $PORT2 'thread_work_total{role="traverse"}' 1 @@ -304,7 +377,7 @@ wait_ready $PORT2 'thread_busy{role="scan"}' 0 # have clients contact the new server export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2 -if type dpkg-deb 2>/dev/null; then +if type bsdtar 2>/dev/null; then # copy in the deb files cp -rvp ${abs_srcdir}/debuginfod-debs/*deb D kill -USR1 $PID2 @@ -321,6 +394,14 @@ fi rm -rf $DEBUGINFOD_CACHE_PATH testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID +# send a request to stress XFF and User-Agent federation relay; +# we'll grep for the two patterns in vlog4 +curl -s -H 'User-Agent: TESTCURL' -H 'X-Forwarded-For: TESTXFF' $DEBUGINFOD_URLS/buildid/deaddeadbeef00000000/debuginfo -o /dev/null || true + +grep UA:TESTCURL vlog4 +grep XFF:TESTXFF vlog4 + + # confirm that first server can't resolve symlinked info in L/ but second can BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \ -a L/foo | grep 'Build ID' | cut -d ' ' -f 7` @@ -349,6 +430,15 @@ curl -s http://127.0.0.1:$PORT2/metrics curl -s http://127.0.0.1:$PORT1/metrics | grep -q 'http_responses_total.*result.*error' curl -s http://127.0.0.1:$PORT1/metrics | grep -q 'http_responses_total.*result.*fdcache' curl -s http://127.0.0.1:$PORT2/metrics | grep -q 'http_responses_total.*result.*upstream' +curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_duration_milliseconds_count' +curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_duration_milliseconds_sum' +curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_count' +curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_sum' + +# And generate a few errors into the second debuginfod's logs, for analysis just below +curl -s http://127.0.0.1:$PORT2/badapi > /dev/null || true +curl -s http://127.0.0.1:$PORT2/buildid/deadbeef/debuginfo > /dev/null || true + ######################################################################## @@ -363,6 +453,13 @@ tempfiles .debuginfod_* testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog2 1 +# check out the debuginfod logs for the new style status lines +# cat vlog3 +grep -q 'UA:.*XFF:.*GET /buildid/.* 200 ' vlog3 +grep -q 'UA:.*XFF:.*GET /metrics 200 ' vlog3 +grep -q 'UA:.*XFF:.*GET /badapi 503 ' vlog3 +grep -q 'UA:.*XFF:.*GET /buildid/deadbeef.* 404 ' vlog3 + ######################################################################## # Add some files to the cache that do not fit its naming format. @@ -396,4 +493,20 @@ kill -int $PID3 wait $PID3 PID3=0 +######################################################################## +# Test fetching a file using file:// . No debuginfod server needs to be run for +# this test. +local_dir=${PWD}/mocktree/buildid/aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd/source/my/path +mkdir -p ${local_dir} +echo "int main() { return 0; }" > ${local_dir}/main.c + +# first test that is doesn't work, when no DEBUGINFOD_URLS is set +DEBUGINFOD_URLS="" +testrun ${abs_top_builddir}/debuginfod/debuginfod-find source aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd /my/path/main.c && false || true + +# Now test is with proper DEBUGINFOD_URLS +DEBUGINFOD_URLS="file://${PWD}/mocktree/" +filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd /my/path/main.c` +cmp $filename ${local_dir}/main.c + exit 0 diff --git a/libdrgn/elfutils/tests/run-getphdrnum.sh b/libdrgn/elfutils/tests/run-getphdrnum.sh new file mode 100755 index 000000000..889cdaf1e --- /dev/null +++ b/libdrgn/elfutils/tests/run-getphdrnum.sh @@ -0,0 +1,137 @@ +#! /bin/sh + +# testfile-phdrs.elf generated with python3 script +# import struct +# import sys +# +# phnum = 66000 +# +# sys.stdout.buffer.write( +# struct.pack( +# "<16BHHIQQQIHHHHHH", +# # EI_MAG +# *b"\x7fELF", +# # EI_CLASS = ELFCLASS64 +# 2, +# # EI_DATA = ELFDATA2LSB +# 1, +# # EI_VERSION +# 1, +# # EI_OSABI = ELFOSABI_SYSV +# 0, +# # EI_ABIVERSION +# 0, +# # EI_PAD +# *bytes(7), +# # e_type = ET_CORE +# 4, +# # e_machine = EM_X86_64 +# 62, +# # e_version +# 1, +# # e_entry +# 0, +# # e_phoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Shdr) +# 128, +# # e_shoff = sizeof(Elf64_Ehdr) +# 64, +# # e_flags +# 0, +# # e_ehsize +# 64, +# # e_phentsize +# 56, +# # e_phnum = PN_XNUM +# 0xFFFF, +# # e_shentsize +# 64, +# # e_shnum +# 1, +# # e_shstrndx +# 0, +# ) +# ) +# +# sys.stdout.buffer.write( +# struct.pack( +# " +#include "hash_table.h" const uint8_t hash_table_empty_chunk_header[16] __attribute__((aligned(16))); diff --git a/libdrgn/hash_table.h b/libdrgn/hash_table.h index bcff5ce27..61eb96f79 100644 --- a/libdrgn/hash_table.h +++ b/libdrgn/hash_table.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright 2018-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ /** @@ -24,7 +24,7 @@ #include #include "cityhash.h" -#include "internal.h" +#include "util.h" /** * @ingroup Internals diff --git a/libdrgn/helpers.h b/libdrgn/helpers.h index be81e6656..e32882d80 100644 --- a/libdrgn/helpers.h +++ b/libdrgn/helpers.h @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright 2019-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ /** @@ -13,6 +13,10 @@ #ifndef DRGN_HELPERS_H #define DRGN_HELPERS_H +struct drgn_error *linux_helper_read_vm(struct drgn_program *prog, + uint64_t pgtable, uint64_t virt_addr, + void *buf, size_t count); + struct drgn_error * linux_helper_radix_tree_lookup(struct drgn_object *res, const struct drgn_object *root, uint64_t index); diff --git a/libdrgn/include/Makefile.am b/libdrgn/include/Makefile.am index 2552a88a6..56d1e0e60 100644 --- a/libdrgn/include/Makefile.am +++ b/libdrgn/include/Makefile.am @@ -26,6 +26,11 @@ gelf.h: ../elfutils/libelf/gelf.h libelf.h: ../elfutils/libelf/libelf.h nlist.h: ../elfutils/libelf/nlist.h +AM_V_CP = $(am__v_CP_@AM_V@) +am__v_CP_ = $(am__v_CP_@AM_DEFAULT_V@) +am__v_CP_0 = @echo " CP " $@; +am__v_CP_1 = + $(BUILT_SOURCES): - mkdir -p $$(dirname $@) - cp $< $@ + $(AM_V_at)mkdir -p $$(dirname $@) + $(AM_V_CP)cp $< $@ diff --git a/libdrgn/internal.c b/libdrgn/internal.c index a733cc7ef..859b28b00 100644 --- a/libdrgn/internal.c +++ b/libdrgn/internal.c @@ -11,32 +11,6 @@ #include #include "internal.h" -/* - * glibc added reallocarray() in 2.26, but since it's so trivial, it's easier to - * duplicate it here than it is to do feature detection. - */ -void *realloc_array(void *ptr, size_t nmemb, size_t size) -{ - size_t bytes; - - if (__builtin_mul_overflow(nmemb, size, &bytes)) { - errno = ENOMEM; - return NULL; - } - return realloc(ptr, bytes); -} - -void *malloc_array(size_t nmemb, size_t size) -{ - size_t bytes; - - if (__builtin_mul_overflow(nmemb, size, &bytes)) { - errno = ENOMEM; - return NULL; - } - return malloc(bytes); -} - struct drgn_error *open_elf_file(const char *path, int *fd_ret, Elf **elf_ret) { struct drgn_error *err; diff --git a/libdrgn/internal.h b/libdrgn/internal.h index 38748eba5..b16ed2ef4 100644 --- a/libdrgn/internal.h +++ b/libdrgn/internal.h @@ -1,27 +1,23 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright 2018-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ /** * @file * - * Miscellanous internal helpers. - * - * Several of these are taken from the Linux kernel source. + * Miscellanous internal drgn helpers. */ #ifndef DRGN_INTERNAL_H #define DRGN_INTERNAL_H -#include #include #include -#include -#include #include #include #include "drgn.h" #include "error.h" +#include "util.h" /** * @@ -36,152 +32,6 @@ #define LIBDRGN_PUBLIC __attribute__((visibility("default"))) #endif -_Static_assert(sizeof(off_t) == 8 || sizeof(off_t) == 4, - "off_t is not 64 bits or 32 bits"); -#define OFF_MAX (sizeof(off_t) == 8 ? INT64_MAX : INT32_MAX) - -#define likely(x) __builtin_expect(!!(x), 1) -#define unlikely(x) __builtin_expect(!!(x), 0) - -#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) -#define __compiletime_error(message) __attribute__((__error__(message))) -#else -#define __compiletime_error(message) -#endif -#ifdef __OPTIMIZE__ -# define __compiletime_assert(condition, msg, prefix, suffix) \ - do { \ - extern void prefix ## suffix(void) __compiletime_error(msg); \ - if (!(condition)) \ - prefix ## suffix(); \ - } while (0) -#else -# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0) -#endif -#define _compiletime_assert(condition, msg, prefix, suffix) \ - __compiletime_assert(condition, msg, prefix, suffix) -#define compiletime_assert(condition, msg) \ - _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) - -#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); })) -#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) - -#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) - -#define ___PASTE(a,b) a##b -#define __PASTE(a,b) ___PASTE(a,b) - -#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) - -#define __typecheck(x, y) \ - (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) - -#define __is_constexpr(x) \ - (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) - -#define __no_side_effects(x, y) \ - (__is_constexpr(x) && __is_constexpr(y)) - -#define __safe_cmp(x, y) \ - (__typecheck(x, y) && __no_side_effects(x, y)) - -#define __cmp(x, y, op) ((x) op (y) ? (x) : (y)) - -#define __cmp_once(x, y, unique_x, unique_y, op) ({ \ - typeof(x) unique_x = (x); \ - typeof(y) unique_y = (y); \ - __cmp(unique_x, unique_y, op); }) - -#define __careful_cmp(x, y, op) \ - __builtin_choose_expr(__safe_cmp(x, y), \ - __cmp(x, y, op), \ - __cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op)) - -#define min(x, y) __careful_cmp(x, y, <) - -#define max(x, y) __careful_cmp(x, y, >) - -#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) - -#define swap(a, b) \ - do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) - -#define container_of(ptr, type, member) ({ \ - void *__mptr = (void *)(ptr); \ - BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ - !__same_type(*(ptr), void), \ - "pointer type mismatch in container_of()"); \ - ((type *)(__mptr - offsetof(type, member))); }) - -#define __bitop(x, unique_x, op) ({ \ - __auto_type unique_x = (x); \ - \ - (unsigned int)(sizeof(unique_x) <= sizeof(unsigned int) ? \ - __builtin_##op(unique_x) : \ - sizeof(unique_x) <= sizeof(unsigned long) ? \ - __builtin_##op##l(unique_x) : \ - __builtin_##op##ll(unique_x)); \ -}) - -#define clz(x) __bitop(x, __UNIQUE_ID(__x), clz) -#define ctz(x) __bitop(x, __UNIQUE_ID(__x), ctz) - -#define __fls(x, unique_x) ({ \ - __auto_type unique_x = (x); \ - \ - unique_x ? 1U + ((8U * max(sizeof(unique_x), \ - sizeof(unsigned int)) - 1U) ^ \ - clz(unique_x)) : 0U; \ -}) - -#define fls(x) __fls(x, __UNIQUE_ID(__x)) - -#define __next_power_of_two(x, unique_x) ({ \ - __auto_type unique_x = (x); \ - \ - unique_x ? (typeof(unique_x))1 << fls(unique_x - 1) : \ - (typeof(unique_x))1; \ -}) - -/** - * Return the smallest power of two greater than or equal to @p x. - * - * Note that zero is not a power of two, so next_power_of_two(0) == 1. - */ -#define next_power_of_two(x) __next_power_of_two(x, __UNIQUE_ID(__x)) - -#define for_each_bit(i, mask) \ - for (i = -1; mask && (i = ctz(mask), mask &= mask - 1, 1);) - -static inline bool strstartswith(const char *s, const char *prefix) -{ - return strncmp(s, prefix, strlen(prefix)) == 0; -} - -void *realloc_array(void *ptr, size_t nmemb, size_t size); -void *malloc_array(size_t nmemb, size_t size); - -/* bool resize_array(T **ptr, size_t n); */ -#define resize_array(ptr, n) ({ \ - __auto_type _ptr = (ptr); \ - typeof(*_ptr) _tmp; \ - bool _success; \ - \ - errno = 0; \ - _tmp = realloc_array(*_ptr, (n), sizeof(**_ptr)); \ - if ((_success = _tmp || !errno)) \ - *_ptr = _tmp; \ - _success; \ -}) - -static inline void *malloc64(uint64_t size) -{ - if (size > SIZE_MAX) - return NULL; - return malloc(size); -} - struct drgn_error *open_elf_file(const char *path, int *fd_ret, Elf **elf_ret); struct drgn_error *find_elf_file(char **path_ret, int *fd_ret, Elf **elf_ret, diff --git a/libdrgn/kdump.c b/libdrgn/kdump.c index b2e77a05d..b352f5e9b 100644 --- a/libdrgn/kdump.c +++ b/libdrgn/kdump.c @@ -125,7 +125,7 @@ struct drgn_error *drgn_program_set_kdump(struct drgn_program *prog) } prog->flags |= DRGN_PROGRAM_IS_LINUX_KERNEL; - err = drgn_program_add_object_finder(prog, vmcoreinfo_object_find, + err = drgn_program_add_object_finder(prog, linux_kernel_object_find, prog); if (err) goto err; diff --git a/libdrgn/language.c b/libdrgn/language.c index 6b32dbe08..ee71aa26f 100644 --- a/libdrgn/language.c +++ b/libdrgn/language.c @@ -39,4 +39,65 @@ const struct drgn_language drgn_languages[] = { .op_neg = c_op_neg, .op_not = c_op_not, }, + [DRGN_LANGUAGE_CPP] = { + .name = "C++", + .void_type = { + { + .kind = DRGN_TYPE_VOID, + .primitive = DRGN_C_TYPE_VOID, + .language = &drgn_language_cpp, + }, + }, + .format_type_name = c_format_type_name, + .format_type = c_format_type, + .format_object = c_format_object, + .find_type = c_find_type, + .bit_offset = c_bit_offset, + .integer_literal = c_integer_literal, + .bool_literal = c_bool_literal, + .float_literal = c_float_literal, + .op_cast = c_op_cast, + .op_bool = c_op_bool, + .op_cmp = c_op_cmp, + .op_add = c_op_add, + .op_sub = c_op_sub, + .op_mul = c_op_mul, + .op_div = c_op_div, + .op_mod = c_op_mod, + .op_lshift = c_op_lshift, + .op_rshift = c_op_rshift, + .op_and = c_op_and, + .op_or = c_op_or, + .op_xor = c_op_xor, + .op_pos = c_op_pos, + .op_neg = c_op_neg, + .op_not = c_op_not, + }, }; + +struct drgn_error *drgn_language_from_die(Dwarf_Die *die, + const struct drgn_language **ret) +{ + Dwarf_Die cudie; + + if (dwarf_cu_info(die->cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL)) + return drgn_error_libdw(); + switch (dwarf_srclang(&cudie)) { + case DW_LANG_C: + case DW_LANG_C89: + case DW_LANG_C99: + case DW_LANG_C11: + *ret = &drgn_language_c; + break; + case DW_LANG_C_plus_plus: + case DW_LANG_C_plus_plus_03: + case DW_LANG_C_plus_plus_11: + case DW_LANG_C_plus_plus_14: + *ret = &drgn_language_cpp; + break; + default: + *ret = NULL; + break; + } + return NULL; +} diff --git a/libdrgn/language.h b/libdrgn/language.h index efbefb96a..c63fdb771 100644 --- a/libdrgn/language.h +++ b/libdrgn/language.h @@ -158,13 +158,14 @@ drgn_unary_op c_op_not; enum { DRGN_LANGUAGE_C, + DRGN_LANGUAGE_CPP, DRGN_NUM_LANGUAGES, }; extern const struct drgn_language drgn_languages[DRGN_NUM_LANGUAGES]; +#define drgn_language_cpp drgn_languages[DRGN_LANGUAGE_CPP] #define drgn_language_c drgn_languages[DRGN_LANGUAGE_C] -#define drgn_default_language drgn_language_c /** * Return flags that should be passed through when formatting an object @@ -202,27 +203,26 @@ drgn_element_format_object_flags(enum drgn_format_object_flags flags) (flags & DRGN_FORMAT_OBJECT_ELEMENT_TYPE_NAMES) >> 2); } -/** Return the @ref drgn_language corresponding to the given DW_LANG */ -static inline const struct drgn_language * -drgn_language_from_dw_lang(int dw_lang) -{ - switch (dw_lang) { - case DW_LANG_C: - case DW_LANG_C89: - case DW_LANG_C99: - case DW_LANG_C11: - return &drgn_language_c; - default: - return &drgn_default_language; - } -} - +/** + * Return the given @ref drgn_language if it is non-@c NULL or the default if it + * is @c NULL. + */ static inline const struct drgn_language * drgn_language_or_default(const struct drgn_language *lang) { - return lang ? lang : &drgn_default_language; + return lang ? lang : &drgn_language_c; } +/** + * Return the @ref drgn_language of the CU of the given DIE. + * + * @param[out] ret Returned language. May be returned as @c NULL if the language + * is unknown. + * @return @c NULL on success, non-@c NULL on error. + */ +struct drgn_error *drgn_language_from_die(Dwarf_Die *die, + const struct drgn_language **ret); + /** @} */ #endif /* DRGN_LANGUAGE_H */ diff --git a/libdrgn/language_c.c b/libdrgn/language_c.c index e810a8e10..8d2c49ac9 100644 --- a/libdrgn/language_c.c +++ b/libdrgn/language_c.c @@ -123,7 +123,7 @@ c_append_tagged_name(struct drgn_qualified_type qualified_type, size_t indent, keyword = "enum"; break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } if (!append_tabs(indent, sb)) @@ -352,7 +352,7 @@ c_declare_variable(struct drgn_qualified_type qualified_type, case DRGN_TYPE_FUNCTION: return c_declare_function(qualified_type, name, indent, sb); } - DRGN_UNREACHABLE(); + UNREACHABLE(); } static struct drgn_error * @@ -507,7 +507,7 @@ c_define_type(struct drgn_qualified_type qualified_type, size_t indent, return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, "function type cannot be formatted"); } - DRGN_UNREACHABLE(); + UNREACHABLE(); } static struct drgn_error * @@ -725,7 +725,7 @@ c_format_int_object(const struct drgn_object *obj, return NULL; } default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } @@ -1007,6 +1007,7 @@ compound_initializer_iter_next(struct initializer_iter *iter_, struct compound_initializer_iter *iter = container_of(iter_, struct compound_initializer_iter, iter); struct compound_initializer_state *top; + uint64_t bit_offset; struct drgn_type_member *member; struct drgn_qualified_type member_type; @@ -1022,6 +1023,7 @@ compound_initializer_iter_next(struct initializer_iter *iter_, continue; } + bit_offset = top->bit_offset; member = top->member++; err = drgn_member_type(member, &member_type); if (err) @@ -1037,7 +1039,7 @@ compound_initializer_iter_next(struct initializer_iter *iter_, !(iter->flags & DRGN_FORMAT_OBJECT_MEMBER_NAMES) || !drgn_type_has_members(member_type.type)) { err = drgn_object_slice(obj_ret, iter->obj, member_type, - top->bit_offset + member->bit_offset, + bit_offset + member->bit_offset, member->bit_field_size); if (err) return err; @@ -1062,7 +1064,7 @@ compound_initializer_iter_next(struct initializer_iter *iter_, return &drgn_enomem; new->member = drgn_type_members(member_type.type); new->end = new->member + drgn_type_num_members(member_type.type); - new->bit_offset = top->bit_offset + member->bit_offset; + new->bit_offset = bit_offset + member->bit_offset; } *flags_ret = iter->member_flags; @@ -1131,7 +1133,7 @@ c_format_compound_object(const struct drgn_object *obj, keyword = "class"; break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } return drgn_error_format(DRGN_ERROR_TYPE, "cannot format incomplete %s object", @@ -1597,7 +1599,7 @@ c_format_object_impl(const struct drgn_object *obj, size_t indent, case DRGN_TYPE_FUNCTION: return c_format_function_object(obj, sb); default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } @@ -2679,7 +2681,7 @@ struct drgn_error *c_bit_offset(struct drgn_program *prog, } break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } state = token.kind; } @@ -2702,10 +2704,7 @@ struct drgn_error *c_integer_literal(struct drgn_object *res, uint64_t uvalue) struct drgn_qualified_type qualified_type; size_t i; - _Static_assert(sizeof(unsigned long long) == 8, - "unsigned long long is not 64 bits"); - bits = uvalue ? 64 - __builtin_clzll(uvalue) : 0; - + bits = fls(uvalue); qualified_type.qualifiers = 0; for (i = 0; i < ARRAY_SIZE(types); i++) { err = drgn_type_index_find_primitive(&res->prog->tindex, @@ -2931,7 +2930,7 @@ c_corresponding_unsigned_type(struct drgn_type_index *tindex, DRGN_C_TYPE_UNSIGNED_LONG_LONG, ret); default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } diff --git a/libdrgn/linux_kernel.c b/libdrgn/linux_kernel.c index f47e3d0c9..4f7801894 100644 --- a/libdrgn/linux_kernel.c +++ b/libdrgn/linux_kernel.c @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright 2018-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ #include @@ -14,10 +14,20 @@ #include "internal.h" #include "dwarf_index.h" +#include "helpers.h" #include "linux_kernel.h" #include "program.h" #include "read.h" +struct drgn_error *read_memory_via_pgtable(void *buf, uint64_t address, + size_t count, uint64_t offset, + void *arg, bool physical) +{ + struct drgn_program *prog = arg; + return linux_helper_read_vm(prog, prog->vmcoreinfo.swapper_pg_dir, + address, buf, count); +} + static inline bool linematch(const char **line, const char *prefix) { size_t len = strlen(prefix); @@ -58,6 +68,7 @@ struct drgn_error *parse_vmcoreinfo(const char *desc, size_t descsz, ret->osrelease[0] = '\0'; ret->page_size = 0; ret->kaslr_offset = 0; + ret->pgtable_l5_enabled = false; while (line < end) { const char *newline; @@ -82,6 +93,18 @@ struct drgn_error *parse_vmcoreinfo(const char *desc, size_t descsz, &ret->kaslr_offset); if (err) return err; + } else if (linematch(&line, "SYMBOL(swapper_pg_dir)=")) { + err = line_to_u64(line, newline, 16, + &ret->swapper_pg_dir); + if (err) + return err; + } else if (linematch(&line, "NUMBER(pgtable_l5_enabled)=")) { + uint64_t tmp; + + err = line_to_u64(line, newline, 0, &tmp); + if (err) + return err; + ret->pgtable_l5_enabled = tmp; } line = newline + 1; } @@ -93,12 +116,16 @@ struct drgn_error *parse_vmcoreinfo(const char *desc, size_t descsz, return drgn_error_create(DRGN_ERROR_OTHER, "VMCOREINFO does not contain valid PAGESIZE"); } - /* KERNELOFFSET is optional. */ + if (!ret->swapper_pg_dir) { + return drgn_error_create(DRGN_ERROR_OTHER, + "VMCOREINFO does not contain valid swapper_pg_dir"); + } + /* KERNELOFFSET and pgtable_l5_enabled are optional. */ return NULL; } -static struct drgn_error *proc_kallsyms_symbol_addr(const char *name, - unsigned long *ret) +struct drgn_error *proc_kallsyms_symbol_addr(const char *name, + unsigned long *ret) { struct drgn_error *err; FILE *file; @@ -118,9 +145,7 @@ static struct drgn_error *proc_kallsyms_symbol_addr(const char *name, err = drgn_error_create_os("getline", errno, "/proc/kallsyms"); } else { - err = drgn_error_format(DRGN_ERROR_OTHER, - "could not find %s symbol in /proc/kallsyms", - name); + err = &drgn_not_found; } break; } @@ -155,20 +180,16 @@ static struct drgn_error *proc_kallsyms_symbol_addr(const char *name, /* * Before Linux kernel commit 23c85094fe18 ("proc/kcore: add vmcoreinfo note to - * /proc/kcore") (in v4.19), /proc/kcore didn't have a VMCOREINFO note, so we - * have to get it by other means. Since Linux kernel commit 464920104bf7 - * ("/proc/kcore: update physical address for kcore ram and text") (in v4.11), + * /proc/kcore") (in v4.19), /proc/kcore didn't have a VMCOREINFO note. Instead, * we can read from the physical address of the vmcoreinfo note exported in - * sysfs. Before that, p_paddr in /proc/kcore is always zero, but we can read - * from the virtual address in /proc/kallsyms. + * sysfs. */ struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, - bool have_non_zero_phys_addr, struct vmcoreinfo *ret) { struct drgn_error *err; FILE *file; - unsigned long address; + uint64_t address; size_t size; char *buf; Elf64_Nhdr *nhdr; @@ -178,32 +199,18 @@ struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, return drgn_error_create_os("fopen", errno, "/sys/kernel/vmcoreinfo"); } - if (fscanf(file, "%lx %zx", &address, &size) != 2) { + if (fscanf(file, "%" SCNx64 "%zx", &address, &size) != 2) { fclose(file); return drgn_error_create(DRGN_ERROR_OTHER, "could not parse /sys/kernel/vmcoreinfo"); } fclose(file); - if (!have_non_zero_phys_addr) { - /* - * Since Linux kernel commit 203e9e41219b ("kexec: move - * vmcoreinfo out of the kernel's .bss section") (in v4.13), - * vmcoreinfo_note is a pointer; before that, it is an array. We - * only do this for kernels before v4.11, so we can assume that - * it's an array. - */ - err = proc_kallsyms_symbol_addr("vmcoreinfo_note", &address); - if (err) - return err; - } - buf = malloc(size); if (!buf) return &drgn_enomem; - err = drgn_memory_reader_read(reader, buf, address, size, - have_non_zero_phys_addr); + err = drgn_memory_reader_read(reader, buf, address, size, true); if (err) goto out; @@ -227,10 +234,10 @@ struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, return err; } -struct drgn_error * -vmcoreinfo_object_find(const char *name, size_t name_len, const char *filename, - enum drgn_find_object_flags flags, void *arg, - struct drgn_object *ret) +struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len, + const char *filename, + enum drgn_find_object_flags flags, + void *arg, struct drgn_object *ret) { struct drgn_error *err; struct drgn_program *prog = arg; @@ -238,8 +245,29 @@ vmcoreinfo_object_find(const char *name, size_t name_len, const char *filename, if (!filename && (flags & DRGN_FIND_OBJECT_CONSTANT)) { struct drgn_qualified_type qualified_type = {}; - if (name_len == strlen("PAGE_SHIFT") && - memcmp(name, "PAGE_SHIFT", name_len) == 0) { + if (name_len == strlen("PAGE_OFFSET") && + memcmp(name, "PAGE_OFFSET", name_len) == 0) { + if (!prog->page_offset) { + if (!prog->has_platform || + !prog->platform.arch->linux_kernel_get_page_offset) + return &drgn_not_found; + err = prog->platform.arch->linux_kernel_get_page_offset(prog, + &prog->page_offset); + if (err) { + prog->page_offset = 0; + return err; + } + } + + err = drgn_type_index_find_primitive(&prog->tindex, + DRGN_C_TYPE_UNSIGNED_LONG, + &qualified_type.type); + if (err) + return err; + return drgn_object_set_unsigned(ret, qualified_type, + prog->page_offset, 0); + } else if (name_len == strlen("PAGE_SHIFT") && + memcmp(name, "PAGE_SHIFT", name_len) == 0) { err = drgn_type_index_find_primitive(&prog->tindex, DRGN_C_TYPE_INT, &qualified_type.type); @@ -289,6 +317,26 @@ vmcoreinfo_object_find(const char *name, size_t name_len, const char *filename, prog->vmcoreinfo.osrelease, 0, 0, DRGN_PROGRAM_ENDIAN); + } else if (name_len == strlen("vmemmap") && + memcmp(name, "vmemmap", name_len) == 0) { + if (!prog->vmemmap) { + if (!prog->has_platform || + !prog->platform.arch->linux_kernel_get_vmemmap) + return &drgn_not_found; + err = prog->platform.arch->linux_kernel_get_vmemmap(prog, + &prog->vmemmap); + if (err) { + prog->vmemmap = 0; + return err; + } + } + + err = drgn_program_find_type(prog, "struct page *", + NULL, &qualified_type); + if (err) + return err; + return drgn_object_set_unsigned(ret, qualified_type, + prog->vmemmap, 0); } } return &drgn_not_found; diff --git a/libdrgn/linux_kernel.h b/libdrgn/linux_kernel.h index 1bc697e66..6bb3b5751 100644 --- a/libdrgn/linux_kernel.h +++ b/libdrgn/linux_kernel.h @@ -12,17 +12,23 @@ struct drgn_dwarf_index; struct drgn_memory_reader; struct vmcoreinfo; +struct drgn_error *read_memory_via_pgtable(void *buf, uint64_t address, + size_t count, uint64_t offset, + void *arg, bool physical); + struct drgn_error *parse_vmcoreinfo(const char *desc, size_t descsz, struct vmcoreinfo *ret); +struct drgn_error *proc_kallsyms_symbol_addr(const char *name, + unsigned long *ret); + struct drgn_error *read_vmcoreinfo_fallback(struct drgn_memory_reader *reader, - bool have_non_zero_phys_addr, struct vmcoreinfo *ret); -struct drgn_error * -vmcoreinfo_object_find(const char *name, size_t name_len, const char *filename, - enum drgn_find_object_flags flags, void *arg, - struct drgn_object *ret); +struct drgn_error *linux_kernel_object_find(const char *name, size_t name_len, + const char *filename, + enum drgn_find_object_flags flags, + void *arg, struct drgn_object *ret); struct drgn_error * linux_kernel_report_debug_info(struct drgn_program *prog, diff --git a/libdrgn/linux_kernel_helpers.c b/libdrgn/linux_kernel_helpers.c index 40216bbad..2365d88cf 100644 --- a/libdrgn/linux_kernel_helpers.c +++ b/libdrgn/linux_kernel_helpers.c @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright 2019-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ #include @@ -7,6 +7,95 @@ #include "internal.h" #include "program.h" +struct drgn_error *linux_helper_read_vm(struct drgn_program *prog, + uint64_t pgtable, uint64_t virt_addr, + void *buf, size_t count) +{ + struct drgn_error *err; + struct pgtable_iterator *it; + pgtable_iterator_next_fn *next; + uint64_t read_addr = 0; + size_t read_size = 0; + + if (!(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL)) { + return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "virtual address translation is only available for the Linux kernel"); + } + if (!prog->has_platform) { + return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "cannot do virtual address translation without platform"); + } + if (!prog->platform.arch->linux_kernel_pgtable_iterator_next) { + return drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT, + "virtual address translation is not implemented for %s architecture", + prog->platform.arch->name); + } + + if (!count) + return NULL; + + if (prog->pgtable_it_in_use) { + return drgn_error_create_fault("recursive address translation; " + "page table may be missing from core dump", + virt_addr); + } + + if (prog->pgtable_it) { + it = prog->pgtable_it; + } else { + it = malloc(sizeof(*it) + + prog->platform.arch->pgtable_iterator_arch_size); + if (!it) + return &drgn_enomem; + prog->pgtable_it = it; + it->prog = prog; + } + it->pgtable = pgtable; + it->virt_addr = virt_addr; + prog->pgtable_it_in_use = true; + prog->platform.arch->pgtable_iterator_arch_init(it->arch); + next = prog->platform.arch->linux_kernel_pgtable_iterator_next; + do { + uint64_t virt_addr, start_virt_addr, end_virt_addr; + uint64_t start_phys_addr, end_phys_addr; + size_t n; + + virt_addr = it->virt_addr; + err = next(it, &start_virt_addr, &start_phys_addr); + if (err) + break; + if (start_phys_addr == UINT64_MAX) { + err = drgn_error_create_fault("address is not mapped", + virt_addr); + break; + } + end_virt_addr = it->virt_addr; + end_phys_addr = start_phys_addr + (end_virt_addr - start_virt_addr); + n = min(end_virt_addr - virt_addr, (uint64_t)count); + if (read_size && end_phys_addr == read_addr + read_size) { + read_size += n; + } else { + if (read_size) { + err = drgn_program_read_memory(prog, buf, + read_addr, + read_size, true); + if (err) + break; + buf = (char *)buf + read_size; + } + read_addr = start_phys_addr + (virt_addr - start_virt_addr); + read_size = n; + } + count -= n; + } while (count); + if (!err) { + err = drgn_program_read_memory(prog, buf, read_addr, read_size, + true); + } + prog->pgtable_it_in_use = false; + return err; +} + struct drgn_error * linux_helper_radix_tree_lookup(struct drgn_object *res, const struct drgn_object *root, uint64_t index) diff --git a/libdrgn/object.c b/libdrgn/object.c index 0ff5085cd..330f96ae9 100644 --- a/libdrgn/object.c +++ b/libdrgn/object.c @@ -268,7 +268,7 @@ static void drgn_value_deserialize(union drgn_value *value, const char *buf, value->fvalue = bit_size == 32 ? tmp.fvalue32 : tmp.fvalue64; break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } @@ -2236,7 +2236,7 @@ INTEGER_BINARY_OP(xor, ^) uint64_t _bit_size = (bit_size); \ union { \ int64_t svalue; \ - int64_t uvalue; \ + uint64_t uvalue; \ } tmp; \ \ _err = drgn_object_convert_signed((obj), _bit_size, &tmp.svalue); \ diff --git a/libdrgn/platform.h b/libdrgn/platform.h index 9410ebe79..bc7f7d206 100644 --- a/libdrgn/platform.h +++ b/libdrgn/platform.h @@ -1,4 +1,4 @@ -// Copyright 2019 - Omar Sandoval +// Copyright 2019-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ #ifndef DRGN_PLATFORM_H @@ -24,6 +24,44 @@ struct drgn_frame_register { const char *pt_regs_name2; }; +/* Page table iterator. */ +struct pgtable_iterator { + struct drgn_program *prog; + /* Address of the top-level page table to iterate. */ + uint64_t pgtable; + /* Current virtual address to translate. */ + uint64_t virt_addr; + /* Architecture-specific data. */ + char arch[0]; +}; + +/* + * Translate the current virtual address from a page table iterator. + * + * Abstractly, a virtual address lies in a range of addresses in the address + * space. A range may be a mapped page, a page table gap, or a range of invalid + * addresses (e.g., non-canonical addresses on x86-64). This finds the range + * containing the current virtual address, returns the first virtual address of + * that range and the physical address it maps to (if any), and updates the + * current virtual address to the end of the range. + * + * This does not merge contiguous ranges. For example, if two adjacent mapped + * pages have adjacent physical addresses, this returns each page separately. + * This makes it possible to distinguish between contiguous pages and "huge + * pages" on architectures that support different page sizes. Similarly, if two + * adjacent entries at level 2 of the page table are empty, this returns each + * gap separately. + * + * @param[in] it Iterator. + * @param[out] virt_addr_ret Returned first virtual address in the range + * containing the current virtual address. + * @param[out] phys_addr_ret Returned physical address that @p virt_addr_ret + * maps to, or @c UINT64_MAX if it is not mapped. + */ +typedef struct drgn_error * +(pgtable_iterator_next_fn)(struct pgtable_iterator *it, uint64_t *virt_addr_ret, + uint64_t *phys_addr_ret); + struct drgn_architecture_info { const char *name; enum drgn_architecture arch; @@ -35,6 +73,19 @@ struct drgn_architecture_info { size_t num_frame_registers; struct drgn_error *(*linux_kernel_set_initial_registers)(Dwfl_Thread *, const struct drgn_object *); + struct drgn_error *(*linux_kernel_get_page_offset)(struct drgn_program *, + uint64_t *); + struct drgn_error *(*linux_kernel_get_vmemmap)(struct drgn_program *, + uint64_t *); + struct drgn_error *(*linux_kernel_live_direct_mapping_fallback)(struct drgn_program *, + uint64_t *, + uint64_t *); + /* Size to allocate for pgtable_iterator::arch. */ + size_t pgtable_iterator_arch_size; + /* Initialize pgtable_iterator::arch. */ + void (*pgtable_iterator_arch_init)(void *buf); + /* Iterate a (user or kernel) page table in the Linux kernel. */ + pgtable_iterator_next_fn *linux_kernel_pgtable_iterator_next; }; static inline const struct drgn_register * diff --git a/libdrgn/program.c b/libdrgn/program.c index ae1c63130..b8a23b902 100644 --- a/libdrgn/program.c +++ b/libdrgn/program.c @@ -84,6 +84,7 @@ void drgn_program_deinit(struct drgn_program *prog) { free(prog->task_state_chars); drgn_prstatus_map_deinit(&prog->prstatus_cache); + free(prog->pgtable_it); drgn_object_index_deinit(&prog->oindex); drgn_type_index_deinit(&prog->tindex); @@ -189,9 +190,8 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) struct drgn_platform platform; bool is_64_bit, is_kdump; size_t phnum, i; - size_t num_file_segments; - bool have_non_zero_phys_addr = false; - struct drgn_memory_file_segment *current_file_segment; + size_t num_file_segments, j; + bool have_phys_addrs = false; const char *vmcoreinfo_note = NULL; size_t vmcoreinfo_size = 0; bool have_nt_taskstruct = false, is_proc_kcore; @@ -253,7 +253,7 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) if (phdr->p_type == PT_LOAD) { if (phdr->p_paddr) - have_non_zero_phys_addr = true; + have_phys_addrs = true; num_file_segments++; } else if (phdr->p_type == PT_NOTE) { Elf_Data *data; @@ -285,6 +285,12 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) nhdr.n_namesz) == 0) { vmcoreinfo_note = desc; vmcoreinfo_size = nhdr.n_descsz; + /* + * This is either a vmcore or + * /proc/kcore, so even a p_paddr of 0 + * may be valid. + */ + have_phys_addrs = true; } } } @@ -309,23 +315,10 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) if (vmcoreinfo_note && !is_proc_kcore) { char *env; - bool use_libkdumpfile; - /* - * Use libkdumpfile for ELF vmcores if we were compiled with - * libkdumpfile support unless specified otherwise. - */ + /* Use libkdumpfile for ELF vmcores if it was requested. */ env = getenv("DRGN_USE_LIBKDUMPFILE_FOR_ELF"); - if (env) { - use_libkdumpfile = atoi(env); - } else { -#ifdef WITH_LIBKDUMPFILE - use_libkdumpfile = true; -#else - use_libkdumpfile = false; -#endif - } - if (use_libkdumpfile) { + if (env && atoi(env)) { err = drgn_program_set_kdump(prog); if (err) goto out_elf; @@ -339,11 +332,23 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) err = &drgn_enomem; goto out_elf; } - prog->num_file_segments = num_file_segments; - current_file_segment = prog->file_segments; + + if (is_proc_kcore || vmcoreinfo_note) { + /* + * Try to read any memory that isn't in the core dump via the + * page table. + */ + err = drgn_program_add_memory_segment(prog, 0, + is_64_bit ? + UINT64_MAX : UINT32_MAX, + read_memory_via_pgtable, + prog, false); + if (err) + goto out_segments; + } /* Second pass: add the segments. */ - for (i = 0; i < phnum; i++) { + for (i = 0, j = 0; i < phnum && j < num_file_segments; i++) { GElf_Phdr phdr_mem, *phdr; phdr = gelf_getphdr(prog->core, i, &phdr_mem); @@ -352,40 +357,78 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) goto out_segments; } - if (phdr->p_type == PT_LOAD) { - /* - * If this happens, then the number of segments changed - * since the first pass. That's probably impossible, but - * skip it just in case. - */ - if (current_file_segment == - prog->file_segments + prog->num_file_segments) - continue; - current_file_segment->file_offset = phdr->p_offset; - current_file_segment->file_size = phdr->p_filesz; - current_file_segment->fd = prog->core_fd; - current_file_segment->eio_is_fault = false; + if (phdr->p_type != PT_LOAD) + continue; + + prog->file_segments[j].file_offset = phdr->p_offset; + prog->file_segments[j].file_size = phdr->p_filesz; + prog->file_segments[j].fd = prog->core_fd; + prog->file_segments[j].eio_is_fault = false; + err = drgn_program_add_memory_segment(prog, phdr->p_vaddr, + phdr->p_memsz, + drgn_read_memory_file, + &prog->file_segments[j], + false); + if (err) + goto out_segments; + if (have_phys_addrs && + phdr->p_paddr != (is_64_bit ? UINT64_MAX : UINT32_MAX)) { err = drgn_program_add_memory_segment(prog, - phdr->p_vaddr, + phdr->p_paddr, phdr->p_memsz, drgn_read_memory_file, - current_file_segment, - false); + &prog->file_segments[j], + true); if (err) goto out_segments; - if (have_non_zero_phys_addr && - phdr->p_paddr != - (is_64_bit ? UINT64_MAX : UINT32_MAX)) { + } + j++; + } + /* + * Before Linux kernel commit 464920104bf7 ("/proc/kcore: update + * physical address for kcore ram and text") (in v4.11), p_paddr in + * /proc/kcore is always zero. If we know the address of the direct + * mapping, we can still add physical segments. This needs to be a third + * pass, as we may need to read virtual memory to determine the mapping. + */ + if (is_proc_kcore && !have_phys_addrs && + platform.arch->linux_kernel_live_direct_mapping_fallback) { + uint64_t direct_mapping, direct_mapping_size; + + err = platform.arch->linux_kernel_live_direct_mapping_fallback(prog, + &direct_mapping, + &direct_mapping_size); + if (err) + goto out_segments; + + for (i = 0, j = 0; i < phnum && j < num_file_segments; i++) { + GElf_Phdr phdr_mem, *phdr; + + phdr = gelf_getphdr(prog->core, i, &phdr_mem); + if (!phdr) { + err = drgn_error_libelf(); + goto out_segments; + } + + if (phdr->p_type != PT_LOAD) + continue; + + if (phdr->p_vaddr >= direct_mapping && + phdr->p_vaddr - direct_mapping + phdr->p_memsz <= + direct_mapping_size) { + uint64_t phys_addr; + + phys_addr = phdr->p_vaddr - direct_mapping; err = drgn_program_add_memory_segment(prog, - phdr->p_paddr, + phys_addr, phdr->p_memsz, drgn_read_memory_file, - current_file_segment, + &prog->file_segments[j], true); if (err) goto out_segments; } - current_file_segment++; + j++; } } if (vmcoreinfo_note) { @@ -398,7 +441,6 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) if (is_proc_kcore) { if (!vmcoreinfo_note) { err = read_vmcoreinfo_fallback(&prog->reader, - have_non_zero_phys_addr, &prog->vmcoreinfo); if (err) goto out_segments; @@ -412,7 +454,7 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) } if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) { err = drgn_program_add_object_finder(prog, - vmcoreinfo_object_find, + linux_kernel_object_find, prog); if (err) goto out_segments; @@ -428,7 +470,6 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path) drgn_memory_reader_init(&prog->reader); free(prog->file_segments); prog->file_segments = NULL; - prog->num_file_segments = 0; out_elf: elf_end(prog->core); prog->core = NULL; @@ -468,7 +509,6 @@ drgn_program_set_pid(struct drgn_program *prog, pid_t pid) prog->file_segments[0].file_size = UINT64_MAX; prog->file_segments[0].fd = prog->core_fd; prog->file_segments[0].eio_is_fault = true; - prog->num_file_segments = 1; err = drgn_program_add_memory_segment(prog, 0, UINT64_MAX, drgn_read_memory_file, prog->file_segments, false); @@ -485,7 +525,6 @@ drgn_program_set_pid(struct drgn_program *prog, pid_t pid) drgn_memory_reader_init(&prog->reader); free(prog->file_segments); prog->file_segments = NULL; - prog->num_file_segments = 0; out_fd: close(prog->core_fd); prog->core_fd = -1; @@ -544,29 +583,6 @@ struct drgn_error *drgn_program_get_dwfl(struct drgn_program *prog, Dwfl **ret) return NULL; } -/* Set the default language from the language of "main". */ -static struct drgn_error * -drgn_program_set_language_from_main(struct drgn_program *prog) -{ - struct drgn_error *err; - struct drgn_object res; - - drgn_object_init(&res, prog); - err = drgn_program_find_object(prog, "main", NULL, DRGN_FIND_OBJECT_ANY, - &res); - if (err) { - if (err->code == DRGN_ERROR_LOOKUP) { - /* We couldn't find "main". Don't set the language. */ - drgn_error_destroy(err); - err = NULL; - } - } else { - prog->lang = drgn_type_language(res.type); - } - drgn_object_deinit(&res); - return err; -} - static struct drgn_error * userspace_report_debug_info(struct drgn_program *prog, struct drgn_dwarf_index *dindex, @@ -614,13 +630,42 @@ userspace_report_debug_info(struct drgn_program *prog, return drgn_error_libdwfl(); } } + return NULL; +} - if (!prog->lang) { - err = drgn_program_set_language_from_main(prog); - if (err) - return err; +/* Set the default language from the language of "main". */ +static void drgn_program_set_language_from_main(struct drgn_program *prog, + struct drgn_dwarf_index *dindex) +{ + struct drgn_error *err; + struct drgn_dwarf_index_iterator it; + static const uint64_t tags[] = { DW_TAG_subprogram }; + + drgn_dwarf_index_iterator_init(&it, dindex, "main", strlen("main"), + tags, ARRAY_SIZE(tags)); + for (;;) { + Dwarf_Die die; + const struct drgn_language *lang; + + err = drgn_dwarf_index_iterator_next(&it, &die, NULL); + if (err == &drgn_stop) { + break; + } else if (err) { + drgn_error_destroy(err); + continue; + } + + err = drgn_language_from_die(&die, &lang); + if (err) { + drgn_error_destroy(err); + continue; + } + + if (lang) { + prog->lang = lang; + break; + } } - return NULL; } static int drgn_set_platform_from_dwarf(Dwfl_Module *module, void **userdatap, @@ -676,10 +721,14 @@ drgn_program_load_debug_info(struct drgn_program *prog, const char **paths, report_from_dwfl = (!(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) && load_main); err = drgn_dwarf_index_report_end(dindex, report_from_dwfl); - if ((!err || err->code == DRGN_ERROR_MISSING_DEBUG_INFO) && - !prog->has_platform) { - dwfl_getdwarf(prog->_dicache->dindex.dwfl, - drgn_set_platform_from_dwarf, prog, 0); + if ((!err || err->code == DRGN_ERROR_MISSING_DEBUG_INFO)) { + if (!prog->lang && + !(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL)) + drgn_program_set_language_from_main(prog, dindex); + if (!prog->has_platform) { + dwfl_getdwarf(dindex->dwfl, + drgn_set_platform_from_dwarf, prog, 0); + } } return err; } @@ -690,17 +739,14 @@ struct drgn_error *drgn_program_cache_prstatus_entry(struct drgn_program *prog, struct drgn_prstatus_map_entry entry; size_t pr_pid_offset; uint32_t pr_pid; - bool bswap; pr_pid_offset = drgn_program_is_64_bit(prog) ? 32 : 24; - bswap = (drgn_program_is_little_endian(prog) != - (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)); if (size < pr_pid_offset + sizeof(pr_pid)) return NULL; memcpy(&pr_pid, data + pr_pid_offset, sizeof(pr_pid)); - if (bswap) + if (drgn_program_bswap(prog)) pr_pid = bswap_32(pr_pid); if (!pr_pid) return NULL; @@ -947,6 +993,73 @@ drgn_program_read_c_string(struct drgn_program *prog, uint64_t address, return NULL; } +LIBDRGN_PUBLIC struct drgn_error * +drgn_program_read_u8(struct drgn_program *prog, uint64_t address, bool physical, + uint8_t *ret) +{ + return drgn_memory_reader_read(&prog->reader, ret, address, + sizeof(*ret), physical); +} + +#define DEFINE_PROGRAM_READ_U(n) \ +LIBDRGN_PUBLIC struct drgn_error * \ +drgn_program_read_u##n(struct drgn_program *prog, uint64_t address, \ + bool physical, uint##n##_t *ret) \ +{ \ + struct drgn_error *err; \ + uint##n##_t tmp; \ + \ + if (!prog->has_platform) { \ + return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, \ + "program byte order is not known"); \ + } \ + err = drgn_memory_reader_read(&prog->reader, &tmp, address, \ + sizeof(tmp), physical); \ + if (err) \ + return err; \ + if (drgn_program_bswap(prog)) \ + tmp = bswap_##n(tmp); \ + *ret = tmp; \ + return NULL; \ +} + +DEFINE_PROGRAM_READ_U(16) +DEFINE_PROGRAM_READ_U(32) +DEFINE_PROGRAM_READ_U(64) +#undef DEFINE_PROGRAM_READ_U + +LIBDRGN_PUBLIC struct drgn_error * +drgn_program_read_word(struct drgn_program *prog, uint64_t address, + bool physical, uint64_t *ret) +{ + struct drgn_error *err; + + if (!prog->has_platform) { + return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT, + "program word size is not known"); + } + if (drgn_program_is_64_bit(prog)) { + uint64_t tmp; + err = drgn_memory_reader_read(&prog->reader, &tmp, address, + sizeof(tmp), physical); + if (err) + return err; + if (drgn_program_bswap(prog)) + tmp = bswap_64(tmp); + *ret = tmp; + } else { + uint32_t tmp; + err = drgn_memory_reader_read(&prog->reader, &tmp, address, + sizeof(tmp), physical); + if (err) + return err; + if (drgn_program_bswap(prog)) + tmp = bswap_32(tmp); + *ret = tmp; + } + return NULL; +} + LIBDRGN_PUBLIC struct drgn_error * drgn_program_find_type(struct drgn_program *prog, const char *name, const char *filename, struct drgn_qualified_type *ret) diff --git a/libdrgn/program.h b/libdrgn/program.h index c4bedffa9..ac1602dbb 100644 --- a/libdrgn/program.h +++ b/libdrgn/program.h @@ -1,4 +1,4 @@ -// Copyright 2018-2019 - Omar Sandoval +// Copyright 2018-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ /** @@ -47,6 +47,10 @@ struct vmcoreinfo { * is enabled. */ uint64_t kaslr_offset; + /** Kernel page table. */ + uint64_t swapper_pg_dir; + /** Whether 5-level paging was enabled. */ + bool pgtable_l5_enabled; }; DEFINE_HASH_MAP_TYPE(drgn_prstatus_map, uint32_t, struct string) @@ -60,13 +64,16 @@ struct drgn_program { struct drgn_type_index tindex; struct drgn_object_index oindex; struct drgn_memory_file_segment *file_segments; - size_t num_file_segments; /* Default language of the program. */ const struct drgn_language *lang; /* * Valid iff flags & DRGN_PROGRAM_IS_LINUX_KERNEL. */ struct vmcoreinfo vmcoreinfo; + /* Cached PAGE_OFFSET. */ + uint64_t page_offset; + /* Cached vmemmap. */ + uint64_t vmemmap; #ifdef WITH_LIBKDUMPFILE kdump_ctx_t *kdump_ctx; #endif @@ -94,7 +101,14 @@ struct drgn_program { bool has_platform; bool attached_dwfl_state; bool prstatus_cached; + /* + * Whether @ref drgn_program::pgtable_it is currently being used. Used + * to prevent address translation from recursing. + */ + bool pgtable_it_in_use; + /* Page table iterator for linux_helper_read_vm(). */ + struct pgtable_iterator *pgtable_it; /* Cache for @ref linux_helper_task_state_to_char(). */ char *task_state_chars; uint64_t task_report; @@ -138,6 +152,16 @@ static inline bool drgn_program_is_little_endian(struct drgn_program *prog) return prog->platform.flags & DRGN_PLATFORM_IS_LITTLE_ENDIAN; } +/** + * Return whether a @ref drgn_program has a different endianness than the host + * system. + */ +static inline bool drgn_program_bswap(struct drgn_program *prog) +{ + return (drgn_program_is_little_endian(prog) != + (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)); +} + static inline bool drgn_program_is_64_bit(struct drgn_program *prog) { assert(prog->has_platform); diff --git a/libdrgn/python/drgnpy.h b/libdrgn/python/drgnpy.h index feffafead..e916f61cf 100644 --- a/libdrgn/python/drgnpy.h +++ b/libdrgn/python/drgnpy.h @@ -287,6 +287,8 @@ struct enum_arg { }; int enum_converter(PyObject *o, void *p); +PyObject *drgnpy_linux_helper_read_vm(PyObject *self, PyObject *args, + PyObject *kwds); DrgnObject *drgnpy_linux_helper_radix_tree_lookup(PyObject *self, PyObject *args, PyObject *kwds); @@ -300,5 +302,7 @@ DrgnObject *drgnpy_linux_helper_find_task(PyObject *self, PyObject *args, PyObject *kwds); PyObject *drgnpy_linux_helper_task_state_to_char(PyObject *self, PyObject *args, PyObject *kwds); +PyObject *drgnpy_linux_helper_pgtable_l5_enabled(PyObject *self, PyObject *args, + PyObject *kwds); #endif /* DRGNPY_H */ diff --git a/libdrgn/python/error.c b/libdrgn/python/error.c index 7f7775dd4..8116fd27a 100644 --- a/libdrgn/python/error.c +++ b/libdrgn/python/error.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" +#include "../error.h" int FaultError_init(PyObject *self, PyObject *args, PyObject *kwds) { diff --git a/libdrgn/python/helpers.c b/libdrgn/python/helpers.c index 0890b32d4..189831bf7 100644 --- a/libdrgn/python/helpers.c +++ b/libdrgn/python/helpers.c @@ -1,9 +1,42 @@ -// Copyright 2019 - Omar Sandoval +// Copyright 2019-2020 - Omar Sandoval // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" #include "../helpers.h" +PyObject *drgnpy_linux_helper_read_vm(PyObject *self, PyObject *args, + PyObject *kwds) +{ + static char *keywords[] = {"prog", "pgtable", "address", "size", NULL}; + struct drgn_error *err; + Program *prog; + struct index_arg pgtable = {}; + struct index_arg address = {}; + Py_ssize_t size; + PyObject *buf; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&O&n:read_vm", + keywords, &Program_type, &prog, + index_converter, &pgtable, + index_converter, &address, &size)) + return NULL; + + if (size < 0) { + PyErr_SetString(PyExc_ValueError, "negative size"); + return NULL; + } + buf = PyBytes_FromStringAndSize(NULL, size); + if (!buf) + return NULL; + err = linux_helper_read_vm(&prog->prog, pgtable.uvalue, address.uvalue, + PyBytes_AS_STRING(buf), size); + if (err) { + Py_DECREF(buf); + return set_drgn_error(err); + } + return buf; +} + DrgnObject *drgnpy_linux_helper_radix_tree_lookup(PyObject *self, PyObject *args, PyObject *kwds) @@ -203,3 +236,21 @@ PyObject *drgnpy_linux_helper_task_state_to_char(PyObject *self, PyObject *args, return set_drgn_error(err); return PyUnicode_FromStringAndSize(&c, 1); } + +PyObject *drgnpy_linux_helper_pgtable_l5_enabled(PyObject *self, PyObject *args, + PyObject *kwds) + +{ + static char *keywords[] = {"prog", NULL}; + Program *prog; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:pgtable_l5_enabled", + keywords, &Program_type, &prog)) + return NULL; + + if ((prog->prog.flags & DRGN_PROGRAM_IS_LINUX_KERNEL) && + prog->prog.vmcoreinfo.pgtable_l5_enabled) + Py_RETURN_TRUE; + else + Py_RETURN_FALSE; +} diff --git a/libdrgn/python/language.c b/libdrgn/python/language.c index d97dd5d0e..d5b9b6e76 100644 --- a/libdrgn/python/language.c +++ b/libdrgn/python/language.c @@ -60,6 +60,7 @@ int add_languages(void) { static const char *attr_names[] = { [DRGN_LANGUAGE_C] = "C", + [DRGN_LANGUAGE_CPP] = "CPP", }; size_t i; diff --git a/libdrgn/python/module.c b/libdrgn/python/module.c index 529722f2f..981c1aed1 100644 --- a/libdrgn/python/module.c +++ b/libdrgn/python/module.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" +#include "../internal.h" #ifdef WITH_KDUMPFILE #include #endif @@ -114,6 +115,8 @@ static PyMethodDef drgn_methods[] = { drgn_array_type_DOC}, {"function_type", (PyCFunction)function_type, METH_VARARGS | METH_KEYWORDS, drgn_function_type_DOC}, + {"_linux_helper_read_vm", (PyCFunction)drgnpy_linux_helper_read_vm, + METH_VARARGS | METH_KEYWORDS}, {"_linux_helper_radix_tree_lookup", (PyCFunction)drgnpy_linux_helper_radix_tree_lookup, METH_VARARGS | METH_KEYWORDS}, @@ -128,6 +131,9 @@ static PyMethodDef drgn_methods[] = { {"_linux_helper_task_state_to_char", (PyCFunction)drgnpy_linux_helper_task_state_to_char, METH_VARARGS | METH_KEYWORDS}, + {"_linux_helper_pgtable_l5_enabled", + (PyCFunction)drgnpy_linux_helper_pgtable_l5_enabled, + METH_VARARGS | METH_KEYWORDS}, {}, }; diff --git a/libdrgn/python/object.c b/libdrgn/python/object.c index 63509149c..99b4b7833 100644 --- a/libdrgn/python/object.c +++ b/libdrgn/python/object.c @@ -323,7 +323,7 @@ static int serialize_py_object(struct drgn_program *prog, char *buf, default: break; } - DRGN_UNREACHABLE(); + UNREACHABLE(); } static int buffer_object_from_value(struct drgn_object *res, @@ -571,7 +571,7 @@ static int DrgnObject_init(DrgnObject *self, PyObject *args, PyObject *kwds) break; } default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } else { PyErr_SetString(PyExc_ValueError, @@ -764,7 +764,7 @@ static PyObject *DrgnObject_value_impl(struct drgn_object *obj) default: break; } - DRGN_UNREACHABLE(); + UNREACHABLE(); } static PyObject *DrgnObject_value(DrgnObject *self) @@ -1214,7 +1214,7 @@ static PyObject *DrgnObject_int(DrgnObject *self) ret = PyLong_FromDouble(value->fvalue); break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } drgn_object_deinit_value(&self->obj, value); return ret; @@ -1247,7 +1247,7 @@ static PyObject *DrgnObject_float(DrgnObject *self) ret = PyFloat_FromDouble(value->fvalue); break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } drgn_object_deinit_value(&self->obj, value); return ret; @@ -1280,7 +1280,7 @@ static PyObject *DrgnObject_index(DrgnObject *self) ret = PyLong_FromUnsignedLongLong(value->uvalue); break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } drgn_object_deinit_value(&self->obj, value); return ret; @@ -1376,7 +1376,7 @@ static PyObject *DrgnObject_##func(DrgnObject *self) \ ret = PyLong_FromDouble(func(value->fvalue)); \ break; \ default: \ - DRGN_UNREACHABLE(); \ + UNREACHABLE(); \ } \ drgn_object_deinit_value(&self->obj, value); \ return ret; \ @@ -1451,14 +1451,28 @@ static PyObject *DrgnObject_getattro(DrgnObject *self, PyObject *attr_name) { struct drgn_error *err; PyObject *attr; - PyObject *exc_type, *exc_value, *exc_traceback; const char *name; DrgnObject *res; + /* + * In Python 3.7 and newer, _PyObject_GenericGetAttrWithDict() can + * suppress the AttributeError if the attribute isn't found. This makes + * member lookups much more efficient. + */ +#define GETATTR_SUPPRESS (PY_VERSION_HEX >= 0x030700b1) +#if GETATTR_SUPPRESS + attr = _PyObject_GenericGetAttrWithDict((PyObject *)self, attr_name, + NULL, 1); + if (attr || PyErr_Occurred()) + return attr; +#else + PyObject *exc_type, *exc_value, *exc_traceback; + attr = PyObject_GenericGetAttr((PyObject *)self, attr_name); if (attr || !PyErr_ExceptionMatches(PyExc_AttributeError)) return attr; PyErr_Fetch(&exc_type, &exc_value, &exc_traceback); +#endif name = PyUnicode_AsUTF8(attr_name); if (!name) { @@ -1480,10 +1494,18 @@ static PyObject *DrgnObject_getattro(DrgnObject *self, PyObject *attr_name) Py_CLEAR(res); if (err->code == DRGN_ERROR_TYPE) { /* - * If the object doesn't have a compound type, - * raise the original AttributeError. + * If the object doesn't have a compound type, raise a + * generic AttributeError (or restore the original one + * if we weren't able to suppress it). */ +#if GETATTR_SUPPRESS + PyErr_Format(PyExc_AttributeError, + "'%s' object has no attribute '%U'", + Py_TYPE(self)->tp_name, attr_name); +#else PyErr_Restore(exc_type, exc_value, exc_traceback); +#endif + drgn_error_destroy(err); return NULL; } else if (err->code == DRGN_ERROR_LOOKUP) { PyErr_SetString(PyExc_AttributeError, err->message); @@ -1491,12 +1513,14 @@ static PyObject *DrgnObject_getattro(DrgnObject *self, PyObject *attr_name) } else { set_drgn_error(err); } - goto out; } out: +#if !GETATTR_SUPPRESS Py_XDECREF(exc_traceback); Py_XDECREF(exc_value); Py_DECREF(exc_type); +#endif +#undef GETATTR_SUPPRESS return (PyObject *)res; } diff --git a/libdrgn/python/program.c b/libdrgn/python/program.c index dfdc11e80..5d4ad9b92 100644 --- a/libdrgn/python/program.c +++ b/libdrgn/python/program.c @@ -2,6 +2,7 @@ // SPDX-License-Identifier: GPL-3.0+ #include "drgnpy.h" +#include "../vector.h" static int Program_hold_object(Program *prog, PyObject *obj) { @@ -417,14 +418,15 @@ static PyObject *Program_set_pid(Program *self, PyObject *args, PyObject *kwds) Py_RETURN_NONE; } +DEFINE_VECTOR(path_arg_vector, struct path_arg) + static PyObject *Program_load_debug_info(Program *self, PyObject *args, PyObject *kwds) { static char *keywords[] = {"paths", "default", "main", NULL}; struct drgn_error *err; PyObject *paths_obj = Py_None; - struct path_arg *path_args = NULL; - size_t n = 0, i; + struct path_arg_vector path_args; const char **paths = NULL; int load_default = 0; int load_main = 0; @@ -434,63 +436,66 @@ static PyObject *Program_load_debug_info(Program *self, PyObject *args, &load_main)) return NULL; + path_arg_vector_init(&path_args); if (paths_obj != Py_None) { Py_ssize_t length_hint; PyObject *it, *item; it = PyObject_GetIter(paths_obj); if (!it) - return NULL; + goto out; length_hint = PyObject_LengthHint(paths_obj, 1); if (length_hint == -1) { Py_DECREF(it); - return NULL; + goto out; } - path_args = calloc(length_hint, sizeof(*path_args)); - if (!path_args) { + if (!path_arg_vector_reserve(&path_args, length_hint)) { + PyErr_NoMemory(); Py_DECREF(it); - return NULL; + goto out; } while ((item = PyIter_Next(it))) { + struct path_arg *path_arg; int ret; - if (n >= length_hint) { - length_hint *= 2; - if (!resize_array(&path_args, length_hint)) { - Py_DECREF(item); - PyErr_NoMemory(); - break; - } + path_arg = path_arg_vector_append_entry(&path_args); + if (!path_arg) { + PyErr_NoMemory(); + Py_DECREF(item); + break; } - ret = path_converter(item, &path_args[n]); + memset(path_arg, 0, sizeof(*path_arg)); + ret = path_converter(item, path_arg); Py_DECREF(item); - if (!ret) + if (!ret) { + path_args.size--; break; - n++; + } } Py_DECREF(it); if (PyErr_Occurred()) goto out; - paths = malloc_array(n, sizeof(*paths)); + paths = malloc_array(path_args.size, sizeof(*paths)); if (!paths) { PyErr_NoMemory(); goto out; } - for (i = 0; i < n; i++) - paths[i] = path_args[i].path; + for (size_t i = 0; i < path_args.size; i++) + paths[i] = path_args.data[i].path; } - err = drgn_program_load_debug_info(&self->prog, paths, n, load_default, - load_main); + err = drgn_program_load_debug_info(&self->prog, paths, path_args.size, + load_default, load_main); free(paths); if (err) set_drgn_error(err); out: - for (i = 0; i < n; i++) - path_cleanup(&path_args[i]); + for (size_t i = 0; i < path_args.size; i++) + path_cleanup(&path_args.data[i]); + path_arg_vector_deinit(&path_args); if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; @@ -540,6 +545,36 @@ static PyObject *Program_read(Program *self, PyObject *args, PyObject *kwds) return buf; } +#define METHOD_READ(x, type) \ +static PyObject *Program_read_##x(Program *self, PyObject *args, \ + PyObject *kwds) \ +{ \ + static char *keywords[] = {"address", "physical", NULL}; \ + struct drgn_error *err; \ + struct index_arg address = {}; \ + int physical = 0; \ + type tmp; \ + \ + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|p:read_"#x, keywords, \ + index_converter, &address, &physical)) \ + return NULL; \ + \ + err = drgn_program_read_##x(&self->prog, address.uvalue, physical, \ + &tmp); \ + if (err) \ + return set_drgn_error(err); \ + if (sizeof(tmp) <= sizeof(unsigned long)) \ + return PyLong_FromUnsignedLong(tmp); \ + else \ + return PyLong_FromUnsignedLongLong(tmp); \ +} +METHOD_READ(u8, uint8_t) +METHOD_READ(u16, uint16_t) +METHOD_READ(u32, uint32_t) +METHOD_READ(u64, uint64_t) +METHOD_READ(word, uint64_t) +#undef METHOD_READ + static PyObject *Program_find_type(Program *self, PyObject *args, PyObject *kwds) { static char *keywords[] = {"name", "filename", NULL}; @@ -868,6 +903,15 @@ static PyMethodDef Program_methods[] = { drgn_Program___getitem___DOC}, {"read", (PyCFunction)Program_read, METH_VARARGS | METH_KEYWORDS, drgn_Program_read_DOC}, +#define METHOD_DEF_READ(x) \ + {"read_"#x, (PyCFunction)Program_read_##x, \ + METH_VARARGS | METH_KEYWORDS, drgn_Program_read_##x##_DOC} + METHOD_DEF_READ(u8), + METHOD_DEF_READ(u16), + METHOD_DEF_READ(u32), + METHOD_DEF_READ(u64), + METHOD_DEF_READ(word), +#undef METHOD_READ_U {"type", (PyCFunction)Program_find_type, METH_VARARGS | METH_KEYWORDS, drgn_Program_type_DOC}, {"pointer_type", (PyCFunction)Program_pointer_type, diff --git a/libdrgn/python/type.c b/libdrgn/python/type.c index 7e3e5ecbb..893b64943 100644 --- a/libdrgn/python/type.c +++ b/libdrgn/python/type.c @@ -9,21 +9,11 @@ static const char *drgn_type_kind_str(struct drgn_type *type) return drgn_type_kind_spelling[drgn_type_kind(type)]; } -static DrgnType *DrgnType_new(enum drgn_qualifiers qualifiers, size_t nmemb, - size_t size) +static DrgnType *DrgnType_new(enum drgn_qualifiers qualifiers) { DrgnType *type_obj; - size_t bytes; - if (__builtin_mul_overflow(nmemb, size, &bytes) || - __builtin_add_overflow(bytes, sizeof(struct drgn_type), &bytes) || - __builtin_add_overflow(bytes, sizeof(void *) - 1, &bytes) || - bytes / sizeof(void *) > PY_SSIZE_T_MAX - sizeof(DrgnType)) { - PyErr_NoMemory(); - return NULL; - } - type_obj = (DrgnType *)DrgnType_type.tp_alloc(&DrgnType_type, - bytes / sizeof(void *)); + type_obj = (DrgnType *)DrgnType_type.tp_alloc(&DrgnType_type, 1); if (!type_obj) return NULL; type_obj->qualifiers = qualifiers; @@ -551,7 +541,8 @@ static void DrgnType_dealloc(DrgnType *self) members = drgn_type_members(self->type); num_members = drgn_type_num_members(self->type); for (i = 0; i < num_members; i++) - drgn_lazy_type_deinit(&members[i].type); + drgn_type_member_deinit(&members[i]); + free(members); } if (drgn_type_has_parameters(self->type)) { struct drgn_type_parameter *parameters; @@ -560,8 +551,11 @@ static void DrgnType_dealloc(DrgnType *self) parameters = drgn_type_parameters(self->type); num_parameters = drgn_type_num_parameters(self->type); for (i = 0; i < num_parameters; i++) - drgn_lazy_type_deinit(¶meters[i].type); + drgn_type_parameter_deinit(¶meters[i]); + free(parameters); } + if (drgn_type_has_enumerators(self->type)) + free(drgn_type_enumerators(self->type)); } Py_XDECREF(self->attr_cache); Py_TYPE(self)->tp_free((PyObject *)self); @@ -873,14 +867,8 @@ PyTypeObject DrgnType_type = { PyVarObject_HEAD_INIT(NULL, 0) .tp_name = "_drgn.Type", .tp_basicsize = sizeof(DrgnType), - /* - * The "item" of a Type object is an optional struct drgn_type + an - * optional array of struct drgn_type_member, struct - * drgn_type_enumerator, or struct drgn_type_parameter. We set - * tp_itemsize to a word so that we can allocate whatever arbitrary size - * we need. - */ - .tp_itemsize = sizeof(void *), + /* The "item" of a Type object is an optional struct drgn_type. */ + .tp_itemsize = sizeof(struct drgn_type), .tp_dealloc = (destructor)DrgnType_dealloc, .tp_repr = (reprfunc)DrgnType_repr, .tp_str = (reprfunc)DrgnType_str, @@ -1326,7 +1314,7 @@ DrgnType *int_type(PyObject *self, PyObject *args, PyObject *kwds) if (!name) return NULL; - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1365,7 +1353,7 @@ DrgnType *bool_type(PyObject *self, PyObject *args, PyObject *kwds) if (!name) return NULL; - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1404,7 +1392,7 @@ DrgnType *float_type(PyObject *self, PyObject *args, PyObject *kwds) if (!name) return NULL; - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1461,7 +1449,7 @@ DrgnType *complex_type(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1482,8 +1470,8 @@ DrgnType *complex_type(PyObject *self, PyObject *args, PyObject *kwds) return type_obj; } -static int unpack_member(DrgnType *type_obj, PyObject *cached_members_obj, - size_t i) +static int unpack_member(struct drgn_type_member *members, + PyObject *cached_members_obj, size_t i) { TypeMember *item; const char *name; @@ -1513,7 +1501,7 @@ static int unpack_member(DrgnType *type_obj, PyObject *cached_members_obj, if (lazy_type_from_py(&member_type, (LazyType *)item) == -1) return -1; - drgn_type_member_init(type_obj->type, i, member_type, name, bit_offset, + drgn_type_member_init(&members[i], member_type, name, bit_offset, bit_field_size); return 0; } @@ -1528,6 +1516,7 @@ static DrgnType *compound_type(PyObject *tag_obj, PyObject *size_obj, DrgnType *type_obj = NULL; unsigned long long size; PyObject *cached_members_obj = NULL; + struct drgn_type_member *members = NULL; size_t num_members; if (tag_obj == Py_None) { @@ -1550,12 +1539,6 @@ static DrgnType *compound_type(PyObject *tag_obj, PyObject *size_obj, drgn_type_kind_spelling[kind]); return NULL; } - type_obj = DrgnType_new(qualifiers, 0, 0); - if (!type_obj) - return NULL; - if (_PyDict_SetItemId(type_obj->attr_cache, - &DrgnType_attr_members.id, Py_None) == -1) - goto err; } else { size_t i; @@ -1578,29 +1561,30 @@ static DrgnType *compound_type(PyObject *tag_obj, PyObject *size_obj, if (!cached_members_obj) return NULL; num_members = PyTuple_GET_SIZE(cached_members_obj); - - type_obj = DrgnType_new(qualifiers, num_members, - sizeof(struct drgn_type_member)); - if (!type_obj) + members = malloc_array(num_members, + sizeof(struct drgn_type_member)); + if (!members) goto err; + for (i = 0; i < num_members; i++) { - if (unpack_member(type_obj, cached_members_obj, - i) == -1) + if (unpack_member(members, cached_members_obj, i) == -1) goto err; } - - if (_PyDict_SetItemId(type_obj->attr_cache, - &DrgnType_attr_members.id, - cached_members_obj) == -1) - goto err; - Py_CLEAR(cached_members_obj); } + type_obj = DrgnType_new(qualifiers); + if (!type_obj) + goto err; + if (_PyDict_SetItemId(type_obj->attr_cache, &DrgnType_attr_tag.id, tag_obj) == -1) goto err; if (members_obj == Py_None) { + if (_PyDict_SetItemId(type_obj->attr_cache, + &DrgnType_attr_members.id, Py_None) == -1) + goto err; + switch (kind) { case DRGN_TYPE_STRUCT: drgn_struct_type_init_incomplete(type_obj->type, tag, @@ -1615,30 +1599,37 @@ static DrgnType *compound_type(PyObject *tag_obj, PyObject *size_obj, language); break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } else { + if (_PyDict_SetItemId(type_obj->attr_cache, + &DrgnType_attr_members.id, + cached_members_obj) == -1) + goto err; + Py_DECREF(cached_members_obj); + switch (kind) { case DRGN_TYPE_STRUCT: drgn_struct_type_init(type_obj->type, tag, size, - num_members, language); + members, num_members, language); break; case DRGN_TYPE_UNION: - drgn_union_type_init(type_obj->type, tag, size, + drgn_union_type_init(type_obj->type, tag, size, members, num_members, language); break; case DRGN_TYPE_CLASS: - drgn_class_type_init(type_obj->type, tag, size, + drgn_class_type_init(type_obj->type, tag, size, members, num_members, language); break; default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } return type_obj; err: Py_XDECREF(type_obj); + free(members); Py_XDECREF(cached_members_obj); return NULL; } @@ -1709,7 +1700,8 @@ DrgnType *class_type(PyObject *self, PyObject *args, PyObject *kwds) language, DRGN_TYPE_CLASS); } -static int unpack_enumerator(DrgnType *type_obj, PyObject *cached_enumerators_obj, +static int unpack_enumerator(struct drgn_type_enumerator *enumerators, + PyObject *cached_enumerators_obj, size_t i, bool is_signed) { TypeEnumerator *item; @@ -1732,7 +1724,7 @@ static int unpack_enumerator(DrgnType *type_obj, PyObject *cached_enumerators_ob svalue = PyLong_AsLongLong(item->value); if (svalue == -1 && PyErr_Occurred()) return -1; - drgn_type_enumerator_init_signed(type_obj->type, i, name, + drgn_type_enumerator_init_signed(&enumerators[i], name, svalue); } else { unsigned long long uvalue; @@ -1740,7 +1732,7 @@ static int unpack_enumerator(DrgnType *type_obj, PyObject *cached_enumerators_ob uvalue = PyLong_AsUnsignedLongLong(item->value); if (uvalue == (unsigned long long)-1 && PyErr_Occurred()) return -1; - drgn_type_enumerator_init_unsigned(type_obj->type, i, name, + drgn_type_enumerator_init_unsigned(&enumerators[i], name, uvalue); } return 0; @@ -1760,6 +1752,7 @@ DrgnType *enum_type(PyObject *self, PyObject *args, PyObject *kwds) unsigned char qualifiers = 0; const struct drgn_language *language = NULL; PyObject *cached_enumerators_obj = NULL; + struct drgn_type_enumerator *enumerators = NULL; size_t num_enumerators; if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|OOO&$O&:enum_type", @@ -1808,13 +1801,6 @@ DrgnType *enum_type(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } num_enumerators = 0; - type_obj = DrgnType_new(qualifiers, 0, 0); - if (!type_obj) - return NULL; - if (_PyDict_SetItemId(type_obj->attr_cache, - &DrgnType_attr_enumerators.id, - Py_None) == -1) - goto err; } else { bool is_signed; size_t i; @@ -1832,26 +1818,25 @@ DrgnType *enum_type(PyObject *self, PyObject *args, PyObject *kwds) cached_enumerators_obj = PySequence_Tuple(enumerators_obj); if (!cached_enumerators_obj) return NULL; - num_enumerators = PyTuple_GET_SIZE(cached_enumerators_obj); - is_signed = drgn_type_is_signed(compatible_type); - type_obj = DrgnType_new(qualifiers, num_enumerators, - sizeof(struct drgn_type_enumerator)); - if (!type_obj) + num_enumerators = PyTuple_GET_SIZE(cached_enumerators_obj); + enumerators = malloc_array(num_enumerators, + sizeof(struct drgn_type_enumerator)); + if (!enumerators) goto err; + is_signed = drgn_type_is_signed(compatible_type); for (i = 0; i < num_enumerators; i++) { - if (unpack_enumerator(type_obj, cached_enumerators_obj, - i, is_signed) == -1) + if (unpack_enumerator(enumerators, + cached_enumerators_obj, i, + is_signed) == -1) goto err; } - - if (_PyDict_SetItemId(type_obj->attr_cache, - &DrgnType_attr_enumerators.id, - cached_enumerators_obj) == -1) - goto err; - Py_CLEAR(cached_enumerators_obj); } + type_obj = DrgnType_new(qualifiers); + if (!type_obj) + goto err; + if (_PyDict_SetItemId(type_obj->attr_cache, &DrgnType_attr_tag.id, tag_obj) == -1) goto err; @@ -1860,15 +1845,27 @@ DrgnType *enum_type(PyObject *self, PyObject *args, PyObject *kwds) goto err; if (enumerators_obj == Py_None) { + if (_PyDict_SetItemId(type_obj->attr_cache, + &DrgnType_attr_enumerators.id, + Py_None) == -1) + goto err; + drgn_enum_type_init_incomplete(type_obj->type, tag, language); } else { + if (_PyDict_SetItemId(type_obj->attr_cache, + &DrgnType_attr_enumerators.id, + cached_enumerators_obj) == -1) + goto err; + Py_DECREF(cached_enumerators_obj); + drgn_enum_type_init(type_obj->type, tag, compatible_type, - num_enumerators, language); + enumerators, num_enumerators, language); } return type_obj; err: Py_XDECREF(type_obj); + free(enumerators); Py_XDECREF(cached_enumerators_obj); return NULL; } @@ -1897,7 +1894,7 @@ DrgnType *typedef_type(PyObject *self, PyObject *args, PyObject *kwds) if (!name) return NULL; - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1934,7 +1931,7 @@ DrgnType *pointer_type(PyObject *self, PyObject *args, PyObject *kwds) language_converter, &language)) return NULL; - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1980,7 +1977,7 @@ DrgnType *array_type(PyObject *self, PyObject *args, PyObject *kwds) return NULL; } - type_obj = DrgnType_new(qualifiers, 0, 0); + type_obj = DrgnType_new(qualifiers); if (!type_obj) return NULL; @@ -1999,8 +1996,8 @@ DrgnType *array_type(PyObject *self, PyObject *args, PyObject *kwds) return type_obj; } -static int unpack_parameter(DrgnType *type_obj, PyObject *cached_parameters_obj, - size_t i) +static int unpack_parameter(struct drgn_type_parameter *parameters, + PyObject *cached_parameters_obj, size_t i) { TypeParameter *item; const char *name; @@ -2022,7 +2019,7 @@ static int unpack_parameter(DrgnType *type_obj, PyObject *cached_parameters_obj, if (lazy_type_from_py(¶meter_type, (LazyType *)item) == -1) return -1; - drgn_type_parameter_init(type_obj->type, i, parameter_type, name); + drgn_type_parameter_init(¶meters[i], parameter_type, name); return 0; } @@ -2036,6 +2033,7 @@ DrgnType *function_type(PyObject *self, PyObject *args, PyObject *kwds) PyObject *return_type_obj; struct drgn_qualified_type return_type; PyObject *parameters_obj, *cached_parameters_obj = NULL; + struct drgn_type_parameter *parameters = NULL; size_t num_parameters, i; int is_variadic = 0; unsigned char qualifiers = 0; @@ -2055,32 +2053,37 @@ DrgnType *function_type(PyObject *self, PyObject *args, PyObject *kwds) cached_parameters_obj = PySequence_Tuple(parameters_obj); if (!cached_parameters_obj) return NULL; - num_parameters = PyTuple_GET_SIZE(cached_parameters_obj); - type_obj = DrgnType_new(qualifiers, num_parameters, - sizeof(struct drgn_type_parameter)); - if (!type_obj) + num_parameters = PyTuple_GET_SIZE(cached_parameters_obj); + parameters = malloc_array(num_parameters, + sizeof(struct drgn_type_parameter)); + if (!parameters) goto err; for (i = 0; i < num_parameters; i++) { - if (unpack_parameter(type_obj, cached_parameters_obj, i) == -1) + if (unpack_parameter(parameters, cached_parameters_obj, i) == -1) goto err; } - if (_PyDict_SetItemId(type_obj->attr_cache, - &DrgnType_attr_parameters.id, - cached_parameters_obj) == -1) + type_obj = DrgnType_new(qualifiers); + if (!type_obj) goto err; - Py_CLEAR(cached_parameters_obj); if (type_arg(return_type_obj, &return_type, type_obj) == -1) goto err; - drgn_function_type_init(type_obj->type, return_type, num_parameters, - is_variadic, language); + if (_PyDict_SetItemId(type_obj->attr_cache, + &DrgnType_attr_parameters.id, + cached_parameters_obj) == -1) + goto err; + Py_DECREF(cached_parameters_obj); + + drgn_function_type_init(type_obj->type, return_type, parameters, + num_parameters, is_variadic, language); return type_obj; err: Py_XDECREF(type_obj); + free(parameters); Py_XDECREF(cached_parameters_obj); return NULL; } diff --git a/libdrgn/read.h b/libdrgn/read.h index 39be595c6..9f0231e93 100644 --- a/libdrgn/read.h +++ b/libdrgn/read.h @@ -122,7 +122,7 @@ static inline void read_u##size##_nocheck(const char **ptr, bool bswap, \ { \ uint##size##_t tmp; \ \ - tmp = *(const uint##size##_t *)*ptr; \ + memcpy(&tmp, *ptr, sizeof(tmp)); \ if (bswap) \ tmp = bswap_##size(tmp); \ *ret = tmp; \ diff --git a/libdrgn/stack_trace.c b/libdrgn/stack_trace.c index 71ad1467a..771009e53 100644 --- a/libdrgn/stack_trace.c +++ b/libdrgn/stack_trace.c @@ -45,7 +45,8 @@ drgn_format_stack_trace(struct drgn_stack_trace *trace, char **ret) struct drgn_stack_frame frame = { .trace = trace, }; for (; frame.i < trace->num_frames; frame.i++) { - uint64_t pc; + Dwarf_Addr pc; + bool isactivation; Dwfl_Module *module; struct drgn_symbol sym; @@ -54,11 +55,12 @@ drgn_format_stack_trace(struct drgn_stack_trace *trace, char **ret) goto err; } - pc = drgn_stack_frame_pc(frame); + dwfl_frame_pc(trace->frames[frame.i], &pc, &isactivation); module = dwfl_frame_module(trace->frames[frame.i]); if (module && drgn_program_find_symbol_by_address_internal(trace->prog, - pc, module, + pc - !isactivation, + module, &sym)) { if (!string_builder_appendf(&str, "%s+0x%" PRIx64 "/0x%" PRIx64, @@ -102,11 +104,14 @@ LIBDRGN_PUBLIC uint64_t drgn_stack_frame_pc(struct drgn_stack_frame frame) LIBDRGN_PUBLIC struct drgn_error * drgn_stack_frame_symbol(struct drgn_stack_frame frame, struct drgn_symbol **ret) { - uint64_t pc; + Dwarf_Addr pc; + bool isactivation; Dwfl_Module *module; struct drgn_symbol *sym; - pc = drgn_stack_frame_pc(frame); + dwfl_frame_pc(frame.trace->frames[frame.i], &pc, &isactivation); + if (!isactivation) + pc--; module = dwfl_frame_module(frame.trace->frames[frame.i]); if (!module) return drgn_error_symbol_not_found(pc); @@ -156,39 +161,24 @@ static bool drgn_thread_memory_read(Dwfl *dwfl, Dwarf_Addr addr, { struct drgn_error *err; struct drgn_program *prog = dwfl_arg; - bool is_little_endian = drgn_program_is_little_endian(prog); - - if (drgn_program_is_64_bit(prog)) { - uint64_t u64; - - err = drgn_program_read_memory(prog, &u64, addr, sizeof(u64), - false); - if (err) - goto err; - *result = is_little_endian ? le64toh(u64) : be64toh(u64); - } else { - uint32_t u32; + uint64_t word; - err = drgn_program_read_memory(prog, &u32, addr, sizeof(u32), - false); - if (err) - goto err; - *result = is_little_endian ? le32toh(u32) : be32toh(u32); + err = drgn_program_read_word(prog, addr, false, &word); + if (err) { + if (err->code == DRGN_ERROR_FAULT) { + /* + * This could be the end of the stack trace, so it shouldn't be + * fatal. + */ + drgn_error_destroy(err); + } else { + drgn_error_destroy(prog->stack_trace_err); + prog->stack_trace_err = err; + } + return false; } + *result = word; return true; - -err: - if (err->code == DRGN_ERROR_FAULT) { - /* - * This could be the end of the stack trace, so it shouldn't be - * fatal. - */ - drgn_error_destroy(err); - } else { - drgn_error_destroy(prog->stack_trace_err); - prog->stack_trace_err = err; - } - return false; } /* @@ -362,7 +352,7 @@ drgn_prstatus_set_initial_registers(Dwfl_Thread *thread, break; } default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } if (!dwfl_thread_state_registers(thread, reg->number, 1, &word)) return drgn_error_libdwfl(); diff --git a/libdrgn/type.c b/libdrgn/type.c index 8f570d75c..aa07da60b 100644 --- a/libdrgn/type.c +++ b/libdrgn/type.c @@ -258,14 +258,15 @@ void drgn_complex_type_init(struct drgn_type *type, const char *name, } void drgn_struct_type_init(struct drgn_type *type, const char *tag, - uint64_t size, size_t num_members, - const struct drgn_language *lang) + uint64_t size, struct drgn_type_member *members, + size_t num_members, const struct drgn_language *lang) { type->_private.kind = DRGN_TYPE_STRUCT; type->_private.is_complete = true; type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.tag = tag; type->_private.size = size; + type->_private.members = members; type->_private.num_members = num_members; type->_private.language = drgn_language_or_default(lang); } @@ -278,19 +279,21 @@ void drgn_struct_type_init_incomplete(struct drgn_type *type, const char *tag, type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.tag = tag; type->_private.size = 0; + type->_private.members = NULL; type->_private.num_members = 0; type->_private.language = drgn_language_or_default(lang); } void drgn_union_type_init(struct drgn_type *type, const char *tag, - uint64_t size, size_t num_members, - const struct drgn_language *lang) + uint64_t size, struct drgn_type_member *members, + size_t num_members, const struct drgn_language *lang) { type->_private.kind = DRGN_TYPE_UNION; type->_private.is_complete = true; type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.tag = tag; type->_private.size = size; + type->_private.members = members; type->_private.num_members = num_members; type->_private.language = drgn_language_or_default(lang); } @@ -303,19 +306,21 @@ void drgn_union_type_init_incomplete(struct drgn_type *type, const char *tag, type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.tag = tag; type->_private.size = 0; + type->_private.members = NULL; type->_private.num_members = 0; type->_private.language = drgn_language_or_default(lang); } void drgn_class_type_init(struct drgn_type *type, const char *tag, - uint64_t size, size_t num_members, - const struct drgn_language *lang) + uint64_t size, struct drgn_type_member *members, + size_t num_members, const struct drgn_language *lang) { type->_private.kind = DRGN_TYPE_CLASS; type->_private.is_complete = true; type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.tag = tag; type->_private.size = size; + type->_private.members = members; type->_private.num_members = num_members; type->_private.language = drgn_language_or_default(lang); } @@ -328,12 +333,14 @@ void drgn_class_type_init_incomplete(struct drgn_type *type, const char *tag, type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.tag = tag; type->_private.size = 0; + type->_private.members = NULL; type->_private.num_members = 0; type->_private.language = drgn_language_or_default(lang); } void drgn_enum_type_init(struct drgn_type *type, const char *tag, struct drgn_type *compatible_type, + struct drgn_type_enumerator *enumerators, size_t num_enumerators, const struct drgn_language *lang) { @@ -344,6 +351,7 @@ void drgn_enum_type_init(struct drgn_type *type, const char *tag, type->_private.tag = tag; type->_private.type = compatible_type; type->_private.qualifiers = 0; + type->_private.enumerators = enumerators; type->_private.num_enumerators = num_enumerators; type->_private.language = drgn_language_or_default(lang); } @@ -357,6 +365,7 @@ void drgn_enum_type_init_incomplete(struct drgn_type *type, const char *tag, type->_private.tag = tag; type->_private.type = NULL; type->_private.qualifiers = 0; + type->_private.enumerators = NULL; type->_private.num_enumerators = 0; type->_private.language = drgn_language_or_default(lang); } @@ -420,6 +429,7 @@ void drgn_array_type_init_incomplete(struct drgn_type *type, void drgn_function_type_init(struct drgn_type *type, struct drgn_qualified_type return_type, + struct drgn_type_parameter *parameters, size_t num_parameters, bool is_variadic, const struct drgn_language *lang) { @@ -428,6 +438,7 @@ void drgn_function_type_init(struct drgn_type *type, type->_private.primitive = DRGN_NOT_PRIMITIVE_TYPE; type->_private.type = return_type.type; type->_private.qualifiers = return_type.qualifiers; + type->_private.parameters = parameters; type->_private.num_parameters = num_parameters; type->_private.is_variadic = is_variadic; type->_private.language = drgn_language_or_default(lang); @@ -822,7 +833,7 @@ LIBDRGN_PUBLIC struct drgn_error *drgn_type_sizeof(struct drgn_type *type, return drgn_error_create(DRGN_ERROR_TYPE, "cannot get size of function type"); } - DRGN_UNREACHABLE(); + UNREACHABLE(); } struct drgn_error *drgn_type_bit_size(struct drgn_type *type, uint64_t *ret) @@ -868,7 +879,7 @@ enum drgn_object_kind drgn_type_object_kind(struct drgn_type *type) case DRGN_TYPE_FUNCTION: return DRGN_OBJECT_NONE; } - DRGN_UNREACHABLE(); + UNREACHABLE(); } struct drgn_error *drgn_type_error(const char *format, struct drgn_type *type) @@ -917,7 +928,7 @@ struct drgn_error *drgn_error_incomplete_type(const char *format, case DRGN_TYPE_VOID: return drgn_error_format(DRGN_ERROR_TYPE, format, "void"); default: - DRGN_UNREACHABLE(); + UNREACHABLE(); } } diff --git a/libdrgn/type.h b/libdrgn/type.h index 16ec92875..46c451e61 100644 --- a/libdrgn/type.h +++ b/libdrgn/type.h @@ -230,24 +230,21 @@ void drgn_complex_type_init(struct drgn_type *type, const char *name, /** * Initialize a member of a type. * - * @param[out] type Type containing member to initialize. - * @param[in] i Index of member to initialize. + * @param[out] members Member to initialize. * @param[in] member_type See @ref drgn_type_member::type. * @param[in] name See @ref drgn_type_member::name. * @param[in] bit_offset See @ref drgn_type_member::bit_offset. * @param[in] bit_field_size See @ref drgn_type_member::bit_field_size. */ -static inline void drgn_type_member_init(struct drgn_type *type, size_t i, +static inline void drgn_type_member_init(struct drgn_type_member *member, struct drgn_lazy_type member_type, const char *name, uint64_t bit_offset, uint64_t bit_field_size) { - struct drgn_type_member *members = drgn_type_payload(type); - - members[i].type = member_type; - members[i].name = name; - members[i].bit_offset = bit_offset; - members[i].bit_field_size = bit_field_size; + member->type = member_type; + member->name = name; + member->bit_offset = bit_offset; + member->bit_field_size = bit_field_size; } /** @@ -255,32 +252,27 @@ static inline void drgn_type_member_init(struct drgn_type *type, size_t i, * * This only frees @ref drgn_type_member::type. * - * @param[out] type Type containing member to free. - * @param[in] i Index of member to free. + * @param[out] member Member to free. */ -static inline void drgn_type_member_deinit(struct drgn_type *type, size_t i) +static inline void drgn_type_member_deinit(struct drgn_type_member *member) { - struct drgn_type_member *members = drgn_type_payload(type); - - drgn_lazy_type_deinit(&members[i].type); + drgn_lazy_type_deinit(&member->type); } /** * Initialize a structure type. * - * @param[out] type Type to initialize. This must have @c num_members @ref - * drgn_type_member%s allocated after it. The members must be initialized with - * @ref drgn_type_member_init() (either before or after this function is - * called). + * @param[out] type Type to initialize. * @param[in] tag Name of the type. This string is not copied. It may be @c NULL * if the type is anonymous. * @param[in] size Size of the type in bytes. + * @param[in] members Members of the type. * @param[in] num_members The number of members in the type. * @param[in] lang Language of this type. */ void drgn_struct_type_init(struct drgn_type *type, const char *tag, - uint64_t size, size_t num_members, - const struct drgn_language *lang); + uint64_t size, struct drgn_type_member *members, + size_t num_members, const struct drgn_language *lang); /** * Initialize an incomplete structure type. @@ -302,42 +294,30 @@ void drgn_struct_type_init_incomplete(struct drgn_type *type, const char *tag, * @sa drgn_struct_type_init(). */ void drgn_union_type_init(struct drgn_type *type, const char *tag, - uint64_t size, size_t num_members, - const struct drgn_language *lang); + uint64_t size, struct drgn_type_member *members, + size_t num_members, const struct drgn_language *lang); /** * Initialize an incomplete union type. * * @sa drgn_struct_type_init_incomplete(). - * @param[in] lang Language of this type. */ void drgn_union_type_init_incomplete(struct drgn_type *type, const char *tag, const struct drgn_language *lang); /** * Initialize a class type. - * @param[out] type Type to initialize. This must have @c num_members @ref - * drgn_type_memer%s allocated after it. Similar to struct type, the members - * must be initialized with @ref drgn_type_member_init() (either before or after - * this function is called). - * @param[in] tag Name of the type. - * @param[in] size Size of the type in bytes. - * @param[in] num_members The number of members in the type. - * @param[in] lang Language of this type. + * + * @sa drgn_struct_type_init(). */ void drgn_class_type_init(struct drgn_type *type, const char *tag, - uint64_t size, size_t num_members, - const struct drgn_language *lang); + uint64_t size, struct drgn_type_member *members, + size_t num_members, const struct drgn_language *lang); /** * Initialize an incomplete class type. * - * @c size and @c num_members are set to zero and @c is_complete is set to @c - * false. - * - * @param[out] type Type to initialize. - * @param[int] tag Name of the type. - * @param[in] lang Language of this type. + * @sa drgn_struct_type_init_incomplete(). */ void drgn_class_type_init_incomplete(struct drgn_type *type, const char *tag, const struct drgn_language *lang); @@ -345,57 +325,48 @@ void drgn_class_type_init_incomplete(struct drgn_type *type, const char *tag, /** * Initialize a signed enumerator of a type. * - * @param[out] type Type containing enumerator to initialize. - * @param[in] i Index of enumerator to initialize. + * @param[out] enumerator Enumerator to initialize. * @param[in] name See @ref drgn_type_enumerator::name. * @param[in] svalue See @ref drgn_type_enumerator::svalue. */ -static inline void drgn_type_enumerator_init_signed(struct drgn_type *type, - size_t i, - const char *name, - int64_t svalue) +static inline void +drgn_type_enumerator_init_signed(struct drgn_type_enumerator *enumerator, + const char *name, int64_t svalue) { - struct drgn_type_enumerator *enumerators = drgn_type_payload(type); - - enumerators[i].name = name; - enumerators[i].svalue = svalue; + enumerator->name = name; + enumerator->svalue = svalue; } /** * Initialize an unsigned enumerator of a type. * - * @param[out] type Type containing enumerator to initialize. - * @param[in] i Index of enumerator to initialize. + * @param[out] enumerator Enumerator to initialize. * @param[in] name See @ref drgn_type_enumerator::name. * @param[in] uvalue See @ref drgn_type_enumerator::uvalue. */ -static inline void drgn_type_enumerator_init_unsigned(struct drgn_type *type, - size_t i, - const char *name, - uint64_t uvalue) +static inline void +drgn_type_enumerator_init_unsigned(struct drgn_type_enumerator *enumerator, + const char *name, uint64_t uvalue) { - struct drgn_type_enumerator *enumerators = drgn_type_payload(type); - - enumerators[i].name = name; - enumerators[i].uvalue = uvalue; + enumerator->name = name; + enumerator->uvalue = uvalue; } /** * Initialize an enumerated type. * - * @param[out] type Type to initialize. This must have @c num_enumerators @ref - * drgn_type_enumerator%s allocated after it. The enumerators must be - * initialized with @ref drgn_type_enumerator_init() (either before or after - * this function is called). + * @param[out] type Type to initialize. * @param[in] tag Name of the type. This string is not copied. It may be @c NULL * if the type is anonymous. * @param[in] compatible_type Type compatible with this enumerated type. It must * be an integer type. + * @param[in] enumerators Enumerators of the type. * @param[in] num_enumerators The number of enumerators in the type. * @param[in] lang Language of this type. */ void drgn_enum_type_init(struct drgn_type *type, const char *tag, struct drgn_type *compatible_type, + struct drgn_type_enumerator *enumerators, size_t num_enumerators, const struct drgn_language *lang); @@ -465,19 +436,16 @@ void drgn_array_type_init_incomplete(struct drgn_type *type, /** * Initialize a parameter of a type. * - * @param[out] type Type containing parameter to initialize. - * @param[in] i Index of parameter to initialize. + * @param[out] parameter Parameter to initialize. * @param[in] parameter_type See @ref drgn_type_parameter::type. * @param[in] name See @ref drgn_type_parameter::name. */ static inline void -drgn_type_parameter_init(struct drgn_type *type, size_t i, +drgn_type_parameter_init(struct drgn_type_parameter *parameter, struct drgn_lazy_type parameter_type, const char *name) { - struct drgn_type_parameter *parameters = drgn_type_payload(type); - - parameters[i].type = parameter_type; - parameters[i].name = name; + parameter->type = parameter_type; + parameter->name = name; } /** @@ -485,23 +453,19 @@ drgn_type_parameter_init(struct drgn_type *type, size_t i, * * This only frees @ref drgn_type_parameter::type. * - * @param[out] type Type containing parameter to free. - * @param[in] i Index of parameter to free. + * @param[out] parameter Parameter to free. */ -static inline void drgn_type_parameter_deinit(struct drgn_type *type, size_t i) +static inline void drgn_type_parameter_deinit(struct drgn_type_parameter *parameter) { - struct drgn_type_parameter *parameters = drgn_type_payload(type); - - drgn_lazy_type_deinit(¶meters[i].type); + drgn_lazy_type_deinit(¶meter->type); } /** * Initialize a function type. * - * @param[out] type Type to initialize. This must have @c num_parameters @ref - * drgn_type_parameter%s allocated after it. The parameters must be initialized - * separately (either before or after this function is called). + * @param[out] type Type to initialize. * @param[in] return_type Type returned by the function type. + * @param[in] parameters Parameters of the function type. * @param[in] num_parameters The number of parameters accepted by the function * type. * @param[in] is_variadic Whether the function type is variadic. @@ -509,6 +473,7 @@ static inline void drgn_type_parameter_deinit(struct drgn_type *type, size_t i) */ void drgn_function_type_init(struct drgn_type *type, struct drgn_qualified_type return_type, + struct drgn_type_parameter *parameters, size_t num_parameters, bool is_variadic, const struct drgn_language *lang); diff --git a/libdrgn/util.h b/libdrgn/util.h new file mode 100644 index 000000000..7a756d7b9 --- /dev/null +++ b/libdrgn/util.h @@ -0,0 +1,181 @@ +// Copyright 2018-2020 - Omar Sandoval +// SPDX-License-Identifier: GPL-3.0+ + +/** + * @file + * + * Miscellanous utility functions. + * + * Several of these are taken from the Linux kernel source. + */ + +#ifndef DRGN_UTIL_H +#define DRGN_UTIL_H + +#include +#include +#include +#include +#include +#include + +#ifdef NDEBUG +#define UNREACHABLE() __builtin_unreachable() +#else +#define UNREACHABLE() assert(!"reachable") +#endif + +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) + +#if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) +#define __compiletime_error(message) __attribute__((__error__(message))) +#else +#define __compiletime_error(message) +#endif +#ifdef __OPTIMIZE__ +# define __compiletime_assert(condition, msg, prefix, suffix) \ + do { \ + extern void prefix ## suffix(void) __compiletime_error(msg); \ + if (!(condition)) \ + prefix ## suffix(); \ + } while (0) +#else +# define __compiletime_assert(condition, msg, prefix, suffix) do { } while (0) +#endif +#define _compiletime_assert(condition, msg, prefix, suffix) \ + __compiletime_assert(condition, msg, prefix, suffix) +#define compiletime_assert(condition, msg) \ + _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__) + +#define BUILD_BUG_ON_ZERO(e) (sizeof(struct { int:(-!!(e)); })) +#define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg) + +#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) + +#define ___PASTE(a,b) a##b +#define __PASTE(a,b) ___PASTE(a,b) + +#define __UNIQUE_ID(prefix) __PASTE(__PASTE(__UNIQUE_ID_, prefix), __COUNTER__) + +#define __typecheck(x, y) \ + (!!(sizeof((typeof(x) *)1 == (typeof(y) *)1))) + +#define __is_constexpr(x) \ + (sizeof(int) == sizeof(*(8 ? ((void *)((long)(x) * 0l)) : (int *)8))) + +#define __no_side_effects(x, y) \ + (__is_constexpr(x) && __is_constexpr(y)) + +#define __safe_cmp(x, y) \ + (__typecheck(x, y) && __no_side_effects(x, y)) + +#define __cmp(x, y, op) ((x) op (y) ? (x) : (y)) + +#define __cmp_once(x, y, unique_x, unique_y, op) ({ \ + typeof(x) unique_x = (x); \ + typeof(y) unique_y = (y); \ + __cmp(unique_x, unique_y, op); }) + +#define __careful_cmp(x, y, op) \ + __builtin_choose_expr(__safe_cmp(x, y), \ + __cmp(x, y, op), \ + __cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op)) + +#define min(x, y) __careful_cmp(x, y, <) + +#define max(x, y) __careful_cmp(x, y, >) + +#define __must_be_array(a) BUILD_BUG_ON_ZERO(__same_type((a), &(a)[0])) +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]) + __must_be_array(arr)) + +#define swap(a, b) \ + do { typeof(a) __tmp = (a); (a) = (b); (b) = __tmp; } while (0) + +#define container_of(ptr, type, member) ({ \ + void *__mptr = (void *)(ptr); \ + BUILD_BUG_ON_MSG(!__same_type(*(ptr), ((type *)0)->member) && \ + !__same_type(*(ptr), void), \ + "pointer type mismatch in container_of()"); \ + ((type *)(__mptr - offsetof(type, member))); }) + +#define __bitop(x, unique_x, op) ({ \ + __auto_type unique_x = (x); \ + static_assert(sizeof(unique_x) <= sizeof(unsigned long long), \ + "type is too large"); \ + (unsigned int)(sizeof(unique_x) <= sizeof(unsigned int) ? \ + op(unique_x) : \ + sizeof(unique_x) <= sizeof(unsigned long) ? \ + op##l(unique_x) : \ + op##ll(unique_x)); \ +}) + +/** + * Return the number of trailing least significant 0-bits in @p x. This is + * undefined if @p x is zero. + */ +#define ctz(x) __bitop(x, __UNIQUE_ID(__x), __builtin_ctz) + +/* + * The straightfoward implementation is bits - clz. However, as noted by the + * folly implementation: "If X is a power of two, X - Y = 1 + ((X - 1) ^ Y). + * Doing this transformation allows GCC to remove its own xor that it adds to + * implement clz using bsr." + * + * This doesn't do the normal macro argument safety stuff because it should only + * be used via __bitop() which already does it. + */ +#define ____fls(x, type, suffix) \ + (x ? 1 + ((8 * sizeof(type) - 1) ^ __builtin_clz##suffix(x)) : 0) +#define __fls(x) ____fls(x, unsigned int,) +#define __flsl(x) ____fls(x, unsigned long, l) +#define __flsll(x) ____fls(x, unsigned long long, ll) + +/** + * Return one plus the index of the most significant 1-bit of @p x or 0 if @p x + * is 0. + */ +#define fls(x) __bitop(x, __UNIQUE_ID(__x), __fls) + +#define __next_power_of_two(x, unique_x) ({ \ + __auto_type unique_x = (x); \ + \ + unique_x ? (typeof(unique_x))1 << fls(unique_x - 1) : \ + (typeof(unique_x))1; \ +}) + +/** + * Return the smallest power of two greater than or equal to @p x. + * + * Note that zero is not a power of two, so next_power_of_two(0) == 1. + */ +#define next_power_of_two(x) __next_power_of_two(x, __UNIQUE_ID(__x)) + +/** Iterate over each 1-bit in @p mask. This modifies @c mask. */ +#define for_each_bit(i, mask) \ + for (i = -1; mask && (i = ctz(mask), mask &= mask - 1, 1);) + +static inline bool strstartswith(const char *s, const char *prefix) +{ + return strncmp(s, prefix, strlen(prefix)) == 0; +} + +static inline void *malloc_array(size_t nmemb, size_t size) +{ + size_t bytes; + + if (__builtin_mul_overflow(nmemb, size, &bytes)) { + errno = ENOMEM; + return NULL; + } + return malloc(bytes); +} + +static inline void *malloc64(uint64_t size) +{ + if (size > SIZE_MAX) + return NULL; + return malloc(size); +} + +#endif /* DRGN_UTIL_H */ diff --git a/scripts/cscope.sh b/scripts/cscope.sh new file mode 100755 index 000000000..52f0b252b --- /dev/null +++ b/scripts/cscope.sh @@ -0,0 +1,3 @@ +#!/bin/sh + +find libdrgn -name '*.[ch]' -o -name '*.[ch].in' | cscope -bq -i- diff --git a/scripts/generate_travis_yml.py b/scripts/generate_travis_yml.py deleted file mode 100755 index b671c7378..000000000 --- a/scripts/generate_travis_yml.py +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env python3 - -""" -We want to test drgn on multiple Python versions on Ubuntu in addition to -multiple kernel versions using the vmtest setup. The .travis.yml build matrix -can't easily express this, so this script generates the jobs manually. -""" - - -PYTHON = ["3.8", "3.7", "3.6"] -KERNEL = ["5.6", "5.5", "5.4", "4.19", "4.14", "4.9", "4.4"] - - -if __name__ == "__main__": - print( - """\ -# Generated by scripts/generate_travis_yml.py - -dist: bionic - -jobs: - include:""" - ) - for python in PYTHON: - print( - f"""\ - - language: python - python: {python} - addons: - apt: - packages: - - libbz2-dev - - liblzma-dev - - zlib1g-dev - install: - script: python setup.py build -j "$(nproc)" test""" - ) - for kernel in KERNEL: - print( - f"""\ - - name: "vmtest Linux {kernel}" - language: minimal - env: KERNEL={kernel} - addons: - apt: - packages: - - python3 - - python3-setuptools - - qemu-kvm - - rsync - - zstd - install: sudo adduser "$USER" kvm - before_script: - # The double sudo is necessary to pick up the new group membership. - - sudo -E sudo -E -u "$USER" scripts/vmtest/run.sh -k "$KERNEL"'.*' -o -d ~ ~/root.img; exitstatus=$? - # Exit status 0 is success, 1 is test failure (should fail in the script - # step), anything else is an error (should fail here). - - test $exitstatus -le 1 - script: test $exitstatus -eq 0""" - ) diff --git a/scripts/vmtest/README.rst b/scripts/vmtest/README.rst deleted file mode 100644 index a1d4dfddf..000000000 --- a/scripts/vmtest/README.rst +++ /dev/null @@ -1,25 +0,0 @@ -drgn VM Testing -=============== - -drgn is tested on multiple Linux kernel versions using QEMU. The tests are run -using an Arch Linux-based root filesystem image and a minimal kernel. - -``scripts/vmtest/run.sh`` downloads the required testing files, sets up the -disk image for the virtual machine, and runs drgn tests in the virtual machine. - -``scripts/vmtest/mkrootfs.sh`` builds the root filesystem image. It must be run -from an Arch Linux machine (or an Arch Linux chroot). The image contains the -dependencies for drgn and a BusyBox init setup. The setup allows ``run.sh`` to -simply copy in the source code and drop in a couple of init scripts to -automatically run tests on boot. - -The root filesystem images and kernel builds are hosted on `Dropbox -`_. -``scripts/vmtest/manage.py`` builds kernels and uploads files to this shared -folder using the Dropbox API. It also updates the ``INDEX`` file in that shared -folder, which is required because the files under a shared folder have -randomly-generated links. - -``scripts/generate_travis_yml.py`` generates ``.travis.yml`` to test all -supported kernel versions (currently the mainline, stable, and longterm -releases from kernel.org). diff --git a/scripts/vmtest/mkrootfs.sh b/scripts/vmtest/mkrootfs.sh deleted file mode 100755 index b25161989..000000000 --- a/scripts/vmtest/mkrootfs.sh +++ /dev/null @@ -1,149 +0,0 @@ -#!/bin/bash - -# This script was inspired by https://github.com/pierres/genbootstrap, which is -# used to generate the official Arch Linux bootstrap images. - -set -euo pipefail - -usage () { - USAGE_STRING="usage: $0 [NAME] - $0 -h - -Build an Arch Linux root filesystem image for testing drgn in a virtual -machine. - -The image is generated as a zstd-compressed tarball. - -This must be run as root, as most of the installation is done in a chroot. - -Arguments: - NAME name of generated image file (default: - drgn-vmtest-rootfs-\$DATE.tar.zst) - -Options: - -h display this help message and exit" - - case "$1" in - out) - echo "$USAGE_STRING" - exit 0 - ;; - err) - echo "$USAGE_STRING" >&2 - exit 1 - ;; - esac -} - -while getopts "h" OPT; do - case "$OPT" in - h) - usage out - ;; - *) - usage err - ;; - esac -done -if [[ $OPTIND -eq $# ]]; then - NAME="${!OPTIND}" -elif [[ $OPTIND -gt $# ]]; then - NAME="drgn-vmtest-rootfs-$(date +%Y.%m.%d).tar.zst" -else - usage err -fi - -pacman_conf= -root= -trap 'rm -rf "$pacman_conf" "$root"' EXIT -pacman_conf="$(mktemp -p "$PWD")" -cat > "$pacman_conf" << "EOF" -[options] -Architecture = auto -CheckSpace -SigLevel = Required DatabaseOptional -[core] -Include = /etc/pacman.d/mirrorlist -[extra] -Include = /etc/pacman.d/mirrorlist -[community] -Include = /etc/pacman.d/mirrorlist -EOF -root="$(mktemp -d -p "$PWD")" - -packages=( - busybox - # Required by some of the packages below. - gettext - # drgn dependencies. - autoconf - automake - bison - bzip2 - flex - gawk - gcc - libtool - make - pkgconf - python - python-setuptools - xz - zlib -) - -pacstrap -C "$pacman_conf" -cGM "$root" "${packages[@]}" - -# Remove unnecessary files from the chroot. - -# We don't need the pacman databases anymore. -rm -rf "$root/var/lib/pacman/sync/" -# We don't need D, Fortran, or Go. -rm -f "$root/usr/lib/libgdruntime."* \ - "$root/usr/lib/libgphobos."* \ - "$root/usr/lib/libgfortran."* \ - "$root/usr/lib/libgo."* -# We don't need the Python test package. -rm -rf "$root/usr/lib/python"*/test -# We don't need any documentation. -rm -rf "$root/usr/share/doc" \ - "$root/usr/share/help" \ - "$root/usr/share/man" \ - "$root/usr/share/texinfo" -# We don't need locale data. -find "$root/usr/share/i18n/locales" "$root/usr/share/locale" \ - -mindepth 1 -maxdepth 1 -not -name POSIX -exec rm -rf {} + - -chroot "$root" /bin/busybox --install - -cat > "$root/etc/fstab" << "EOF" -dev /dev devtmpfs rw,nosuid 0 0 -proc /proc proc rw,nosuid,nodev,noexec 0 0 -sys /sys sysfs rw,nosuid,nodev,noexec 0 0 -EOF -chmod 644 "$root/etc/fstab" - -cat > "$root/etc/inittab" << "EOF" -::sysinit:/etc/init.d/rcS -::ctrlaltdel:/sbin/reboot -::shutdown:/sbin/swapoff -a -::shutdown:/bin/umount -a -r -::restart:/sbin/init -EOF -chmod 644 "$root/etc/inittab" - -mkdir -m 755 "$root/etc/init.d" "$root/etc/rcS.d" -cat > "$root/etc/init.d/rcS" << "EOF" -#!/bin/sh - -/bin/mount -a - -for path in /etc/rcS.d/S*; do - [ -x "$path" ] && "$path" -done -EOF -chmod 755 "$root/etc/init.d/rcS" - -chmod 755 "$root" -tar -C "$root" -c . | zstd -T0 -19 -o "$NAME" -chmod 644 "$NAME" diff --git a/scripts/vmtest/run.sh b/scripts/vmtest/run.sh deleted file mode 100755 index f1541bc50..000000000 --- a/scripts/vmtest/run.sh +++ /dev/null @@ -1,410 +0,0 @@ -#!/bin/bash - -set -uo pipefail -trap 'exit 2' ERR - -usage () { - USAGE_STRING="usage: $0 [-k KERNELRELEASE|-b DIR] [[-r ROOTFSVERSION] [-fo]|-I] [-Si] [-d DIR] IMG - $0 [-k KERNELRELEASE] -l - $0 -h - -Run drgn tests in a virtual machine. - -This exits with status 0 on success, 1 if the virtual machine ran successfully -but tests failed, and 2 if we encountered a fatal error. - -This script uses sudo to mount and modify the disk image. - -Arguments: - IMG path of virtual machine disk image to create - -Versions: - -k, --kernel=KERNELRELEASE - kernel release to test. This is a glob pattern; the - newest (sorted by version number) release that matches - the pattern is used (default: newest available release) - - -b, --build DIR use the kernel built in the given directory. This option - cannot be combined with -k - - -r, --rootfs=ROOTFSVERSION - version of root filesystem to use (default: newest - available version) - -Setup: - -f, --force overwrite IMG if it already exists - - -o, --one-shot one-shot mode. By default, this script saves a clean copy - of the downloaded root filesystem image and vmlinux and - makes a copy (reflinked, when possible) for executing the - virtual machine. This allows subsequent runs to skip - downloading these files. If this option is given, the - root filesystem image and vmlinux are always - re-downloaded and are not saved. This option implies -f - - -I, --skip-image skip creating the disk image; use the existing one at - IMG. This option cannot be combined with -r, -f, or -o - - -S, --skip-source skip copying the source files and init scripts - -Miscellaneous: - -i, --interactive interactive mode. Boot the virtual machine into an - interactive shell instead of automatically running tests - - -d, --dir=DIR working directory to use for downloading and caching - files (default: current working directory) - - -l, --list list available kernel releases instead of running tests. - The list may be filtered with -k - - -h, --help display this help message and exit" - - case "$1" in - out) - echo "$USAGE_STRING" - exit 0 - ;; - err) - echo "$USAGE_STRING" >&2 - exit 2 - ;; - esac -} - -TEMP=$(getopt -o 'k:b:r:foISid:lh' --long 'kernel:,build:,rootfs:,force,one-shot,skip-image,skip-source,interactive,dir:,list,help' -n "$0" -- "$@") -eval set -- "$TEMP" -unset TEMP - -unset KERNELRELEASE -unset BUILDDIR -unset ROOTFSVERSION -unset IMG -FORCE=0 -ONESHOT=0 -SKIPIMG=0 -SKIPSOURCE=0 -APPEND="" -DIR="$PWD" -LIST=0 -while true; do - case "$1" in - -k|--kernel) - KERNELRELEASE="$2" - shift 2 - ;; - -b|--build) - BUILDDIR="$2" - shift 2 - ;; - -r|--rootfs) - ROOTFSVERSION="$2" - shift 2 - ;; - -f|--force) - FORCE=1 - shift - ;; - -o|--one-shot) - ONESHOT=1 - FORCE=1 - shift - ;; - -I|--skip-image) - SKIPIMG=1 - shift - ;; - -S|--skip-source) - SKIPSOURCE=1 - shift - ;; - -i|--interactive) - APPEND=" single" - shift - ;; - -d|--dir) - DIR="$2" - shift 2 - ;; - -l|--list) - LIST=1 - ;; - -h|--help) - usage out - ;; - --) - shift - break - ;; - *) - usage err - ;; - esac -done -if [[ -v BUILDDIR ]]; then - if [[ -v KERNELRELEASE ]]; then - usage err - fi -elif [[ ! -v KERNELRELEASE ]]; then - KERNELRELEASE='*' -fi -if [[ $SKIPIMG -ne 0 && ( -v ROOTFSVERSION || $FORCE -ne 0 ) ]]; then - usage err -fi -if (( LIST )); then - if [[ $# -ne 0 || -v BUILDDIR || -v ROOTFSVERSION || $FORCE -ne 0 || - $SKIPIMG -ne 0 || $SKIPSOURCE -ne 0 || -n $APPEND ]]; then - usage err - fi -else - if [[ $# -ne 1 ]]; then - usage err - fi - IMG="${!OPTIND}" -fi - -unset URLS -cache_urls() { - if ! declare -p URLS &> /dev/null; then - # This URL contains a mapping from file names to URLs where - # those files can be downloaded. - local INDEX='https://www.dropbox.com/sh/2mcf2xvg319qdaw/AAC_AbpvQPRrHF-99B2REpXja/x86_64/INDEX?dl=1' - declare -gA URLS - while IFS=$'\t' read -r name url; do - URLS["$name"]="$url" - done < <(curl -LfsS "$INDEX") - fi -} - -matching_kernel_releases() { - local pattern="$1" - { - for file in "${!URLS[@]}"; do - if [[ $file =~ ^vmlinux-(.*).zst$ ]]; then - release="${BASH_REMATCH[1]}" - case "$release" in - $pattern) - # sort -V handles rc versions properly - # if we use "~" instead of "-". - echo "${release//-rc/~rc}" - ;; - esac - fi - done - } | sort -rV | sed 's/~rc/-rc/g' -} - -newest_rootfs_version() { - { - for file in "${!URLS[@]}"; do - if [[ $file =~ ^drgn-vmtest-rootfs-(.*)\.tar\.zst$ ]]; then - echo "${BASH_REMATCH[1]}" - fi - done - } | sort -rV | head -1 -} - -download() { - local file="$1" - cache_urls - if [[ ! -v URLS[$file] ]]; then - echo "$file not found" >&2 - return 1 - fi - echo "Downloading $file..." >&2 - curl -Lf "${URLS[$file]}" "${@:2}" -} - -set_nocow() { - touch "$@" - chattr +C "$@" >/dev/null 2>&1 || true -} - -cp_img() { - set_nocow "$2" - cp --reflink=auto "$1" "$2" -} - -create_rootfs_img() { - local path="$1" - set_nocow "$path" - truncate -s 2G "$path" - mkfs.ext4 -q "$path" -} - -download_rootfs() { - local rootfsversion="$1" - local dir="$2" - download "drgn-vmtest-rootfs-$rootfsversion.tar.zst" | - zstd -d | sudo tar -C "$dir" -x -} - -if (( LIST )); then - cache_urls - matching_kernel_releases "$KERNELRELEASE" - exit 0 -fi - -if [[ $FORCE -eq 0 && $SKIPIMG -eq 0 && -e $IMG ]]; then - echo "$IMG already exists; use -f to overwrite it or -I to reuse it" >&2 - exit 1 -fi - -# Only go to the network if it's actually a glob pattern. -if [[ -v BUILDDIR ]]; then - KERNELRELEASE="$(make -C "$BUILDDIR" -s kernelrelease)" -elif [[ ! $KERNELRELEASE =~ ^([^\\*?[]|\\[*?[])*\\?$ ]]; then - # We need to cache the list of URLs outside of the command - # substitution, which happens in a subshell. - cache_urls - KERNELRELEASE="$(matching_kernel_releases "$KERNELRELEASE" | head -1)" - if [[ -z $KERNELRELEASE ]]; then - echo "No matching kernel release found" >&2 - exit 1 - fi -fi -if [[ $SKIPIMG -eq 0 && ! -v ROOTFSVERSION ]]; then - cache_urls - ROOTFSVERSION="$(newest_rootfs_version)" -fi - -echo "Kernel release: $KERNELRELEASE" >&2 -if (( SKIPIMG )); then - echo "Not extracting root filesystem" >&2 -else - echo "Root filesystem version: $ROOTFSVERSION" >&2 -fi -echo "Disk image: $IMG" >&2 - -tmp= -ARCH_DIR="$DIR/x86_64" -mkdir -p "$ARCH_DIR" -mnt="$(mktemp -d -p "$DIR" mnt.XXXXXXXXXX)" - -cleanup() { - if [[ -n $tmp ]]; then - rm -f "$tmp" || true - fi - if mountpoint -q "$mnt"; then - sudo umount "$mnt" || true - fi - if [[ -d "$mnt" ]]; then - rmdir "$mnt" || true - fi -} -trap cleanup EXIT - -if [[ -v BUILDDIR ]]; then - vmlinuz="$BUILDDIR/$(make -C "$BUILDDIR" -s image_name)" -else - vmlinuz="$ARCH_DIR/vmlinuz-$KERNELRELEASE" - if [[ ! -e $vmlinuz ]]; then - tmp="$(mktemp "$vmlinuz.XXX.part")" - download "vmlinuz-$KERNELRELEASE" -o "$tmp" - mv "$tmp" "$vmlinuz" - tmp= - fi -fi - -# Mount and set up the rootfs image. -if (( ONESHOT )); then - rm -f "$IMG" - create_rootfs_img "$IMG" - sudo mount -o loop "$IMG" "$mnt" - download_rootfs "$ROOTFSVERSION" "$mnt" -else - if (( ! SKIPIMG )); then - rootfs_img="$ARCH_DIR/drgn-vmtest-rootfs-$ROOTFSVERSION.img" - - if [[ ! -e $rootfs_img ]]; then - tmp="$(mktemp "$rootfs_img.XXX.part")" - set_nocow "$tmp" - truncate -s 2G "$tmp" - mkfs.ext4 -q "$tmp" - sudo mount -o loop "$tmp" "$mnt" - - download_rootfs "$ROOTFSVERSION" "$mnt" - - sudo umount "$mnt" - mv "$tmp" "$rootfs_img" - tmp= - fi - - rm -f "$IMG" - cp_img "$rootfs_img" "$IMG" - fi - sudo mount -o loop "$IMG" "$mnt" -fi - -# Install vmlinux. -vmlinux="$mnt/boot/vmlinux-$KERNELRELEASE" -if [[ -v BUILDDIR || $ONESHOT -eq 0 ]]; then - if [[ -v BUILDDIR ]]; then - source_vmlinux="$BUILDDIR/vmlinux" - else - source_vmlinux="$ARCH_DIR/vmlinux-$KERNELRELEASE" - if [[ ! -e $source_vmlinux ]]; then - tmp="$(mktemp "$source_vmlinux.XXX.part")" - download "vmlinux-$KERNELRELEASE.zst" | zstd -dfo "$tmp" - mv "$tmp" "$source_vmlinux" - tmp= - fi - fi - echo "Copying vmlinux..." >&2 - sudo rsync -cp --chmod 0644 "$source_vmlinux" "$vmlinux" -else - # We could use "sudo zstd -o", but let's not run zstd as root with - # input from the internet. - download "vmlinux-$KERNELRELEASE.zst" | - zstd -d | sudo tee "$vmlinux" > /dev/null - sudo chmod 644 "$vmlinux" -fi - -if (( SKIPSOURCE )); then - echo "Not copying source files..." >&2 -else - "${PYTHON:-python3}" setup.py egg_info - - echo "Copying source files..." >&2 - - # Copy the source files in. - sudo mkdir -p -m 0755 "$mnt/drgn" - sudo rsync --files-from=drgn.egg-info/SOURCES.txt -cpt . "$mnt/drgn" - - # Create the init scripts. - sudo tee "$mnt/etc/rcS.d/S50-run-tests" > /dev/null << "EOF" -#!/bin/sh - -# Force the Linux helper tests to run and fail if they would be skipped -# otherwise. -export DRGN_RUN_LINUX_HELPER_TESTS=1 -cd /drgn && python3 --version && python3 setup.py build test -echo $? > /exitstatus -chmod 644 /exitstatus -EOF - sudo chmod 755 "$mnt/etc/rcS.d/S50-run-tests" - - sudo tee "$mnt/etc/rcS.d/S99-poweroff" > /dev/null << "EOF" -#!/bin/sh - -poweroff -EOF - sudo chmod 755 "$mnt/etc/rcS.d/S99-poweroff" -fi - -sudo umount "$mnt" - -echo "Starting virtual machine..." >&2 -qemu-system-x86_64 -nodefaults -display none -serial mon:stdio \ - -cpu kvm64 -enable-kvm -smp "$(nproc)" -m 2G \ - -drive file="$IMG",format=raw,index=1,media=disk,if=virtio,cache=none \ - -kernel "$vmlinuz" -append "root=/dev/vda rw console=ttyS0,115200$APPEND" - -sudo mount -o loop "$IMG" "$mnt" -if exitstatus="$(cat "$mnt/exitstatus" 2>/dev/null)"; then - printf '\nTests exit status: %s\n' "$exitstatus" >&2 -else - printf '\nCould not read tests exit status\n' >&2 - exitstatus=1 -fi -sudo umount "$mnt" -exit "$exitstatus" diff --git a/setup.py b/setup.py index d14e6a9c1..143a2466e 100755 --- a/setup.py +++ b/setup.py @@ -4,12 +4,13 @@ from distutils import log from distutils.command.build import build as _build from distutils.dir_util import mkpath +from distutils.errors import DistutilsError from distutils.file_util import copy_file import os import os.path import re import pkg_resources -from setuptools import setup, find_packages +from setuptools import setup, find_packages, Command from setuptools.command.build_ext import build_ext as _build_ext from setuptools.command.egg_info import egg_info as _egg_info from setuptools.extension import Extension @@ -17,20 +18,14 @@ import subprocess import sys +from util import nproc, out_of_date + class build(_build): def finalize_options(self): super().finalize_options() if self.parallel is None: - self.parallel = len(os.sched_getaffinity(0)) + 1 - - -def out_of_date(path, *deps): - try: - mtime = os.stat(path).st_mtime - except FileNotFoundError: - return True - return any(os.stat(dep).st_mtime > mtime for dep in deps) + self.parallel = nproc() + 1 class build_ext(_build_ext): @@ -124,6 +119,120 @@ def run(self): super().run() +class test(Command): + description = "run unit tests after in-place build" + + KERNELS = ["5.7", "5.6", "5.5", "5.4", "4.19", "4.14", "4.9", "4.4"] + + user_options = [ + ( + "kernel", + "K", + "run Linux kernel helper tests in a virtual machine on all supported kernels " + f"({', '.join(KERNELS)})", + ), + ( + "extra-kernels=", + "k", + "additional kernels to run Linux kernel helper tests on in a virtual machine " + "(comma-separated list of kernel build directory path or " + "wildcard pattern matching uploaded kernel release strings)", + ), + ( + "vmtest-dir=", + "d", + "directory for built artifacts and downloaded kernels for virtual machine tests (default: 'build/vmtest')", + ), + ] + + def initialize_options(self): + self.kernel = False + self.extra_kernels = "" + self.vmtest_dir = None + + def finalize_options(self): + self.kernels = [kernel for kernel in self.extra_kernels.split(",") if kernel] + if self.kernel: + self.kernels.extend(kernel + ".*" for kernel in test.KERNELS) + if self.vmtest_dir is None: + build_base = self.get_finalized_command("build").build_base + self.vmtest_dir = os.path.join(build_base, "vmtest") + + def _run_local(self): + import unittest + + argv = ["discover"] + if self.verbose: + argv.append("-v") + test = unittest.main(module=None, argv=argv, exit=False) + return test.result.wasSuccessful() + + def _run_vm(self, *, vmlinux, vmlinuz, build_dir): + import vmtest.vm + + command = fr"""cd {shlex.quote(os.getcwd())} && + DRGN_RUN_LINUX_HELPER_TESTS=1 {shlex.quote(sys.executable)} -Bm \ + unittest discover -t . -s tests/helpers/linux {"-v" if self.verbose else ""}""" + command = vmtest.vm.install_vmlinux_precommand(command, vmlinux) + try: + returncode = vmtest.vm.run_in_vm( + command, vmlinuz=vmlinuz, build_dir=build_dir + ) + except vmtest.vm.LostVMError as e: + self.announce(f"error: {e}", log.ERROR) + return False + self.announce(f"Tests in VM returned {returncode}", log.INFO) + return returncode == 0 + + def run(self): + import vmtest.resolver + + # Start downloads ASAP so that they're hopefully done by the time we + # need them. + with vmtest.resolver.KernelResolver(self.kernels, self.vmtest_dir) as resolver: + if self.kernels: + self.announce( + "downloading/preparing kernels in the background", log.INFO + ) + self.run_command("egg_info") + self.reinitialize_command("build_ext", inplace=1) + self.run_command("build_ext") + + passed = [] + failed = [] + + if self.kernels: + self.announce("running tests locally", log.INFO) + if self._run_local(): + passed.append("local") + else: + failed.append("local") + + if self.kernels: + for kernel in resolver: + self.announce( + f"running tests in VM on Linux {kernel.release}", log.INFO + ) + if self._run_vm( + vmlinux=kernel.vmlinux, + vmlinuz=kernel.vmlinuz, + build_dir=self.vmtest_dir, + ): + passed.append(kernel.release) + else: + failed.append(kernel.release) + + if passed: + self.announce(f'Passed: {", ".join(passed)}', log.INFO) + if failed: + self.announce(f'Failed: {", ".join(failed)}', log.ERROR) + + if failed: + raise DistutilsError("some tests failed") + else: + self.announce("all tests passed", log.INFO) + + def get_version(): if not os.path.exists(".git"): # If this is a source distribution, get the version from the egg @@ -183,7 +292,12 @@ def get_version(): # This is here so that setuptools knows that we have an extension; it's # actually built using autotools/make. ext_modules=[Extension(name="_drgn", sources=[])], - cmdclass={"build": build, "build_ext": build_ext, "egg_info": egg_info}, + cmdclass={ + "build": build, + "build_ext": build_ext, + "egg_info": egg_info, + "test": test, + }, entry_points={"console_scripts": ["drgn=drgn.internal.cli:main"],}, python_requires=">=3.6", author="Omar Sandoval", diff --git a/tests/helpers/linux/__init__.py b/tests/helpers/linux/__init__.py index b57977db0..b0f96f3a4 100644 --- a/tests/helpers/linux/__init__.py +++ b/tests/helpers/linux/__init__.py @@ -121,6 +121,17 @@ def umount(target, flags=0): raise OSError(errno, os.strerror(errno), target) +_mlock = _c.mlock +_mlock.restype = ctypes.c_int +_mlock.argtypes = [ctypes.c_void_p, ctypes.c_size_t] + + +def mlock(addr, len): + if _mlock(addr, len) == -1: + errno = ctypes.get_errno() + raise OSError(errno, os.strerror(errno)) + + def create_socket(*args, **kwds): try: return socket.socket(*args, **kwds) diff --git a/tests/helpers/linux/test_mm.py b/tests/helpers/linux/test_mm.py new file mode 100644 index 000000000..7227915a1 --- /dev/null +++ b/tests/helpers/linux/test_mm.py @@ -0,0 +1,137 @@ +import contextlib +import ctypes +import mmap +import os +import platform +import re +import struct +import tempfile +import unittest + +from drgn import FaultError +from drgn.helpers.linux.mm import ( + access_process_vm, + access_remote_vm, + cmdline, + environ, + page_to_pfn, + pfn_to_page, + pfn_to_virt, + pgtable_l5_enabled, + virt_to_pfn, +) +from drgn.helpers.linux.pid import find_task +from tests.helpers.linux import LinuxHelperTestCase, mlock + + +class TestMm(LinuxHelperTestCase): + def test_page_constants(self): + self.assertEqual(self.prog["PAGE_SIZE"], mmap.PAGESIZE) + self.assertEqual(1 << self.prog["PAGE_SHIFT"], mmap.PAGESIZE) + self.assertEqual(~self.prog["PAGE_MASK"] + 1, mmap.PAGESIZE) + + # Returns an mmap.mmap object for a file mapping, its mapped address, and + # the pfns backing it. + @contextlib.contextmanager + def _pages(self): + if not os.path.exists("/proc/self/pagemap"): + self.skipTest("kernel does not support pagemap") + + pages = 4 + with tempfile.TemporaryFile() as f: + f.write(os.urandom(pages * mmap.PAGESIZE)) + f.flush() + with mmap.mmap(f.fileno(), pages * mmap.PAGESIZE) as map: + f.close() + address = ctypes.addressof(ctypes.c_char.from_buffer(map)) + # Make sure the pages are faulted in and stay that way. + mlock(address, pages * mmap.PAGESIZE) + + with open("/proc/self/pagemap", "rb", buffering=0) as pagemap: + pagemap.seek(address // mmap.PAGESIZE * 8) + pfns = [ + entry & ((1 << 54) - 1) + for entry in struct.unpack(f"{pages}Q", pagemap.read(pages * 8)) + ] + yield map, address, pfns + + def test_virt_to_from_pfn(self): + with self._pages() as (map, _, pfns): + for i, pfn in enumerate(pfns): + virt = pfn_to_virt(self.prog, pfn) + # Test that we got the correct virtual address by reading from + # it and comparing it to the mmap. + self.assertEqual( + self.prog.read(virt, mmap.PAGESIZE), + map[i * mmap.PAGESIZE : (i + 1) * mmap.PAGESIZE], + ) + # Test the opposite direction. + self.assertEqual(virt_to_pfn(virt), pfn) + + def test_pfn_to_from_page(self): + with self._pages() as (map, _, pfns): + for i, pfn in enumerate(pfns): + page = pfn_to_page(self.prog, pfn) + # Test that we got the correct page by looking at the index: it + # should be page i in the file. + self.assertEqual(page.index, i) + # Test the opposite direction. + self.assertEqual(page_to_pfn(page), pfn) + + def test_read_physical(self): + with self._pages() as (map, _, pfns): + for i, pfn in enumerate(pfns): + self.assertEqual( + self.prog.read(pfn * mmap.PAGESIZE, mmap.PAGESIZE, True), + map[i * mmap.PAGESIZE : (i + 1) * mmap.PAGESIZE], + ) + + def test_access_process_vm(self): + task = find_task(self.prog, os.getpid()) + data = b"hello, world" + buf = ctypes.create_string_buffer(data) + address = ctypes.addressof(buf) + self.assertEqual(access_process_vm(task, address, len(data)), data) + self.assertEqual(access_remote_vm(task.mm, address, len(data)), data) + self.assertRaises(FaultError, access_process_vm, task, 0, 8) + + def test_access_process_vm_big(self): + task = find_task(self.prog, os.getpid()) + with self._pages() as (map, address, _): + self.assertEqual(access_process_vm(task, address, len(map)), map[:]) + self.assertEqual( + access_process_vm(task, address + 1, len(map) - 1), map[1:] + ) + self.assertEqual( + access_process_vm(task, address + 1, len(map) - 2), map[1:-1] + ) + + @unittest.skipUnless(platform.machine() == "x86_64", "machine is not x86_64") + def test_non_canonical_x86_64(self): + task = find_task(self.prog, os.getpid()) + data = b"hello, world" + buf = ctypes.create_string_buffer(data) + address = ctypes.addressof(buf) + self.assertRaises( + FaultError, access_process_vm, task, address ^ (1 << 63), len(data) + ) + + def test_cmdline(self): + with open("/proc/self/cmdline", "rb") as f: + proc_cmdline = f.read().split(b"\0")[:-1] + task = find_task(self.prog, os.getpid()) + self.assertEqual(cmdline(task), proc_cmdline) + + def test_environ(self): + with open("/proc/self/environ", "rb") as f: + proc_environ = f.read().split(b"\0")[:-1] + task = find_task(self.prog, os.getpid()) + self.assertEqual(environ(task), proc_environ) + + @unittest.skipUnless(platform.machine() == "x86_64", "machine is not x86_64") + def test_pgtable_l5_enabled(self): + with open("/proc/cpuinfo", "r") as f: + self.assertEqual( + pgtable_l5_enabled(self.prog), + bool(re.search(r"flags\s*:.*\bla57\b", f.read())), + ) diff --git a/tests/test_dwarf.py b/tests/test_dwarf.py index f983c336a..acf43610a 100644 --- a/tests/test_dwarf.py +++ b/tests/test_dwarf.py @@ -2060,6 +2060,14 @@ def test_language(self): self.assertEqual( dwarf_program(dies, lang=DW_LANG.BLISS).language, DEFAULT_LANGUAGE ) + self.assertEqual( + dwarf_program(dies, lang=DW_LANG.C_plus_plus_14).language, Language.CPP + ) + + self.assertEqual( + dwarf_program(dies, lang=DW_LANG.C_plus_plus).object("main").type_.language, + Language.CPP, + ) def test_reference_counting(self): # Test that we keep the appropriate objects alive even if we don't have diff --git a/tests/test_object.py b/tests/test_object.py index eece89665..6121cfbb9 100644 --- a/tests/test_object.py +++ b/tests/test_object.py @@ -1485,6 +1485,10 @@ def test_neg(self): self.assertEqual(-Object(self.prog, "unsigned char", value=1), self.int(-1)) self.assertEqual(-self.int(-1), self.int(1)) self.assertEqual(-self.unsigned_int(1), self.unsigned_int(0xFFFFFFFF)) + self.assertEqual( + -Object(self.prog, "long", value=-0x8000000000000000), + Object(self.prog, "long", value=-0x8000000000000000), + ) self.assertEqual(-self.double(2.0), self.double(-2.0)) self.assertRaisesRegex( TypeError, diff --git a/tests/test_program.py b/tests/test_program.py index 89c6736de..090fad079 100644 --- a/tests/test_program.py +++ b/tests/test_program.py @@ -134,10 +134,37 @@ def test_language(self): class TestMemory(unittest.TestCase): def test_simple_read(self): data = b"hello, world" - prog = mock_program(segments=[MockMemorySegment(data, 0xFFFF0000, 0xA0),]) + prog = mock_program(segments=[MockMemorySegment(data, 0xFFFF0000, 0xA0)]) self.assertEqual(prog.read(0xFFFF0000, len(data)), data) self.assertEqual(prog.read(0xA0, len(data), True), data) + def test_read_unsigned(self): + data = b"\x01\x02\x03\x04\x05\x06\x07\x08" + for word_size in [8, 4]: + for byteorder in ["little", "big"]: + flags = PlatformFlags(0) + if word_size == 8: + flags |= PlatformFlags.IS_64_BIT + if byteorder == "little": + flags |= PlatformFlags.IS_LITTLE_ENDIAN + prog = mock_program( + Platform(Architecture.UNKNOWN, flags), + segments=[MockMemorySegment(data, 0xFFFF0000, 0xA0)], + ) + for size in [1, 2, 4, 8]: + read_fn = getattr(prog, f"read_u{8 * size}") + value = int.from_bytes(data[:size], byteorder) + self.assertEqual(read_fn(0xFFFF0000), value) + self.assertEqual(read_fn(0xA0, True), value) + if size == word_size: + self.assertEqual(prog.read_word(0xFFFF0000), value) + self.assertEqual(prog.read_word(0xA0, True), value) + + prog = mock_program( + MOCK_32BIT_PLATFORM, + segments=[MockMemorySegment(data, 0xFFFF0000, 0xA0)], + ) + def test_bad_address(self): data = b"hello, world!" prog = mock_program(segments=[MockMemorySegment(data, 0xFFFF0000)]) diff --git a/tests/test_type.py b/tests/test_type.py index df93bcc20..c7986eaa3 100644 --- a/tests/test_type.py +++ b/tests/test_type.py @@ -1165,6 +1165,10 @@ def test_language(self): self.assertEqual(void_type(language=None).language, DEFAULT_LANGUAGE) self.assertEqual(void_type(language=Language.C).language, Language.C) + self.assertEqual( + int_type("int", 4, True, language=Language.CPP).language, Language.CPP + ) + def test_cmp(self): self.assertEqual(void_type(), void_type()) self.assertEqual(void_type(Qualifiers.CONST), void_type(Qualifiers.CONST)) diff --git a/tests/test_util.py b/tests/test_util.py new file mode 100644 index 000000000..bf5cef82f --- /dev/null +++ b/tests/test_util.py @@ -0,0 +1,27 @@ +from functools import cmp_to_key +import unittest + +from util import KernelVersion, verrevcmp + + +class TestUtil(unittest.TestCase): + def assertVersionSort(self, sorted_list): + self.assertEqual(sorted(sorted_list, key=cmp_to_key(verrevcmp)), sorted_list) + + def test_verrevcmp(self): + self.assertVersionSort( + ["0~", "0", "1", "1.0", "1.1~rc1", "1.1~rc2", "1.1", "1.2", "1.12"] + ) + self.assertVersionSort(["a", "."]) + self.assertVersionSort(["", "1"]) + self.assertVersionSort(["~", "~1"]) + self.assertVersionSort(["~~", "~~a", "~", "", "a"]) + + def test_kernel_version(self): + self.assertLess(KernelVersion("1.0"), KernelVersion("2.0")) + self.assertLess(KernelVersion("5.6.0-rc6"), KernelVersion("5.6.0-rc7")) + self.assertLess(KernelVersion("5.6.0-rc7"), KernelVersion("5.6.0")) + self.assertLess( + KernelVersion("5.6.0-rc7-vmtest2"), KernelVersion("5.6.0-vmtest1") + ) + self.assertLess(KernelVersion("5.6.0-vmtest1"), KernelVersion("5.6.0-vmtest2")) diff --git a/tools/bpf_inspect.py b/tools/bpf_inspect.py index 650e22869..c4ac6c1d0 100755 --- a/tools/bpf_inspect.py +++ b/tools/bpf_inspect.py @@ -21,9 +21,7 @@ BpfMapType = enum_type_to_class(prog.type("enum bpf_map_type"), "BpfMapType") BpfProgType = enum_type_to_class(prog.type("enum bpf_prog_type"), "BpfProgType") -BpfAttachType = enum_type_to_class( - prog.type("enum bpf_attach_type"), "BpfAttachType" -) +BpfAttachType = enum_type_to_class(prog.type("enum bpf_attach_type"), "BpfAttachType") def get_btf_name(btf, btf_id): @@ -106,9 +104,7 @@ def list_bpf_progs(args): type_ = BpfProgType(bpf_prog.type).name name = get_prog_name(bpf_prog) - linked = ", ".join( - [get_linked_func(p) for p in get_tramp_progs(bpf_prog)] - ) + linked = ", ".join([get_linked_func(p) for p in get_tramp_progs(bpf_prog)]) if linked: linked = f" linked:[{linked}]" @@ -132,14 +128,10 @@ def main(): subparsers = parser.add_subparsers(title="subcommands", dest="subcommand") subparsers.required = True - prog_parser = subparsers.add_parser( - "prog", aliases=["p"], help="list BPF programs" - ) + prog_parser = subparsers.add_parser("prog", aliases=["p"], help="list BPF programs") prog_parser.set_defaults(func=list_bpf_progs) - map_parser = subparsers.add_parser( - "map", aliases=["m"], help="list BPF maps" - ) + map_parser = subparsers.add_parser("map", aliases=["m"], help="list BPF maps") map_parser.set_defaults(func=list_bpf_maps) args = parser.parse_args() diff --git a/util.py b/util.py new file mode 100644 index 000000000..982bd9553 --- /dev/null +++ b/util.py @@ -0,0 +1,109 @@ +# Copyright 2020 - Omar Sandoval +# SPDX-License-Identifier: GPL-3.0+ + +from functools import total_ordering +import os +import re + + +def nproc() -> int: + return len(os.sched_getaffinity(0)) + + +def out_of_date(path: str, *deps: str) -> bool: + try: + mtime = os.stat(path).st_mtime + except FileNotFoundError: + return True + return any(os.stat(dep).st_mtime > mtime for dep in deps) + + +def _c_isdigit(c: int) -> bool: + # '0' <= c <= '9' + return 0x30 <= c <= 0x39 + + +def _c_isalpha(c: int) -> bool: + # ('A' <= c <= 'Z') or ('a' <= c <= 'z') + return (0x41 <= c <= 0x5A) or (0x61 <= c <= 0x7A) + + +def _order(c: int) -> int: + if _c_isdigit(c): + return 0 + elif _c_isalpha(c): + return c + elif c == 0x7E: # '~' + return -1 + else: + return c + 0x100 + + +def verrevcmp(v1: str, v2: str) -> int: + """ + Compare two versions according to the coreutils version sort rules + (https://www.gnu.org/software/coreutils/manual/html_node/Version_002dsort-ordering-rules.html). + Returns 0 if v1 == v2 by this definition, < 0 if v1 < v2, and > 0 if v1 > + v2. + + Adapted from + https://git.savannah.gnu.org/cgit/gnulib.git/tree/lib/filevercmp.c. + """ + # By definition, version sort compares ASCII, not Unicode: + # https://www.gnu.org/software/coreutils/manual/html_node/Version-sort-ignores-locale.html. + s1 = bytearray(v1, "utf-8") + s2 = bytearray(v2, "utf-8") + s1_len = len(s1) + s2_len = len(s2) + # Add sentinels to avoid some length checks. + s1.append(0) + s2.append(0) + s1_pos = s2_pos = 0 + while s1_pos < s1_len or s2_pos < s2_len: + while (s1_pos < s1_len and not _c_isdigit(s1[s1_pos])) or ( + s2_pos < s2_len and not _c_isdigit(s2[s2_pos]) + ): + s1_c = _order(s1[s1_pos]) if s1_pos < s1_len else 0 + s2_c = _order(s2[s2_pos]) if s2_pos < s2_len else 0 + if s1_c != s2_c: + return s1_c - s2_c + s1_pos += 1 + s2_pos += 1 + while s1[s1_pos] == 0x30: # '0' + s1_pos += 1 + while s2[s2_pos] == 0x30: # '0' + s2_pos += 1 + first_diff = 0 + while _c_isdigit(s1[s1_pos]) and _c_isdigit(s2[s2_pos]): + if not first_diff: + first_diff = s1[s1_pos] - s2[s2_pos] + s1_pos += 1 + s2_pos += 1 + if _c_isdigit(s1[s1_pos]): + return 1 + if _c_isdigit(s2[s2_pos]): + return -1 + if first_diff: + return first_diff + return 0 + + +@total_ordering +class KernelVersion: + """ + Version ordered by verrevcmp(), with -rc releases before the final release. + """ + + def __init__(self, release: str) -> None: + # ~ sorts before anything, including the end of the version. + self._key = re.sub(r"-(rc[0-9])", r"~\1", release) + + def __eq__(self, other: object) -> bool: + if not isinstance(other, KernelVersion): + return NotImplemented + return self._key == other._key + + def __lt__(self, other: object) -> bool: + if not isinstance(other, KernelVersion): + return NotImplemented + return verrevcmp(self._key, other._key) < 0 diff --git a/vmtest/README.rst b/vmtest/README.rst new file mode 100644 index 000000000..f57c78f1c --- /dev/null +++ b/vmtest/README.rst @@ -0,0 +1,47 @@ +drgn VM Testing +=============== + +drgn has a significant amount of code (both core and in helpers) which is +dependent on the Linux kernel version. This code is tested on multiple Linux +kernel versions in a virtual machine. These tests can be run on all supported +kernels with ``python3 setup.py test -K``. This requires QEMU and zstd to be +installed. + +Tests can also be run on specific kernels with ``-k``. This takes a +comma-separated list of kernels which are either a wildcard pattern (e.g., +``5.6.*``) that matches a kernel release hosted on Dropbox (see below) or a +kernel build directory path starting with ``.`` or ``/``. + +Architecture +------------ + +The goal of vmtest is to run tests in the same userspace environment as the +host, but with a different kernel. The host runs the virtual machine with `QEMU +`_ (see the `vmtest.vm `_ module). + +The guest mounts the host's root filesystem as its own root filesystem via +`VirtFS `_. It is mounted read-only for +safety. To support modifications, the guest uses `OverlayFS +`_ to +overlay a read-write tmpfs over the VirtFS root. + +The guest runs a `BusyBox `_ shell script as init +which sets up the system and filesystem hierarchy, runs a command, and returns +the exit status via `virtio-serial +`_. + +This infrastructure is all generic. The drgn-specific parts are: + +1. The kernel builds. The `kernel configuration `_ includes everything + required to run drgn and the Linux kernel helper tests. These builds are + hosted on `Dropbox + `_. + They are managed via the Dropbox API by the `vmtest.manage `_ CLI + and downloaded by the `vmtest.resolver `_ module. +2. The test command itself. This is just some ``setup.py`` glue, a command to + install vmlinux where drgn can find it, and the proper invocation of the + Python `unittest command line interface + `_. + +The ``vmtest.vm`` and ``vmtest.resolver`` modules also have CLIs for testing +purposes. These are subject to change. diff --git a/vmtest/__init__.py b/vmtest/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/vmtest/config b/vmtest/config new file mode 100644 index 000000000..bf8ce5217 --- /dev/null +++ b/vmtest/config @@ -0,0 +1,57 @@ +# Minimal Linux kernel configuration for booting into vmtest and running drgn +# tests. + +CONFIG_LOCALVERSION="-vmtest1" + +CONFIG_SMP=y + +# No modules to simplify installing the kernel into the root filesystem image. +CONFIG_MODULES=n + +# We run the tests in KVM. +CONFIG_HYPERVISOR_GUEST=y +CONFIG_KVM_GUEST=y +CONFIG_PARAVIRT=y +CONFIG_PARAVIRT_SPINLOCKS=y + +# Minimum requirements for vmtest. +CONFIG_9P_FS=y +CONFIG_DEVTMPFS=y +CONFIG_INET=y +CONFIG_NET=y +CONFIG_NETWORK_FILESYSTEMS=y +CONFIG_NET_9P=y +CONFIG_NET_9P_VIRTIO=y +CONFIG_OVERLAY_FS=y +CONFIG_PCI=y +CONFIG_PROC_FS=y +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SYSFS=y +CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_VIRTIO_CONSOLE=y +CONFIG_VIRTIO_PCI=y + +# drgn needs /proc/kcore for live debugging. +CONFIG_PROC_KCORE=y +# In some cases, it also needs /proc/kallsyms. +CONFIG_KALLSYMS=y +CONFIG_KALLSYMS_ALL=y + +# drgn needs debug info. +CONFIG_DEBUG_KERNEL=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_DWARF4=y + +# Before Linux kernel commit 8757dc970f55 ("x86/crash: Define +# arch_crash_save_vmcoreinfo() if CONFIG_CRASH_CORE=y") (in v5.6), some +# important information in VMCOREINFO is initialized by the kexec code. +CONFIG_KEXEC=y + +# For block tests. +CONFIG_BLK_DEV_LOOP=y + +# For kconfig tests. +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y diff --git a/scripts/vmtest/manage.py b/vmtest/manage.py old mode 100755 new mode 100644 similarity index 72% rename from scripts/vmtest/manage.py rename to vmtest/manage.py index 748d32dc7..7b121f14e --- a/scripts/vmtest/manage.py +++ b/vmtest/manage.py @@ -1,4 +1,5 @@ -#!/usr/bin/env python3 +# Copyright 2020 - Omar Sandoval +# SPDX-License-Identifier: GPL-3.0+ import aiohttp import argparse @@ -8,14 +9,30 @@ import io import json import logging -import multiprocessing import os import os.path import re import shlex +import shutil import sys import time +from typing import ( + Any, + AsyncGenerator, + BinaryIO, + Dict, + List, + Optional, + Set, + SupportsFloat, + SupportsRound, + TextIO, + Tuple, +) import urllib.parse +from yarl import URL + +from util import nproc logger = logging.getLogger("asyncio") @@ -24,58 +41,11 @@ KERNEL_ORG_JSON = "https://www.kernel.org/releases.json" -DEFCONFIG = """\ -# Minimal configuration for booting into the root filesystem image and building -# and testing drgn on a live kernel. - -CONFIG_SMP=y - -# No modules to simplify installing the kernel into the root filesystem image. -CONFIG_MODULES=n - -# We run the tests in KVM. -CONFIG_HYPERVISOR_GUEST=y -CONFIG_KVM_GUEST=y -CONFIG_PARAVIRT=y -CONFIG_PARAVIRT_SPINLOCKS=y - -# Minimum requirements for booting up. -CONFIG_DEVTMPFS=y -CONFIG_EXT4_FS=y -CONFIG_PCI=y -CONFIG_PROC_FS=y -CONFIG_SERIAL_8250=y -CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SYSFS=y -CONFIG_VIRTIO_BLK=y -CONFIG_VIRTIO_PCI=y - -# drgn needs /proc/kcore for live debugging. -CONFIG_PROC_KCORE=y -# In some cases, it also needs /proc/kallsyms. -CONFIG_KALLSYMS=y -CONFIG_KALLSYMS_ALL=y - -# drgn needs debug info. -CONFIG_DEBUG_KERNEL=y -CONFIG_DEBUG_INFO=y -CONFIG_DEBUG_INFO_DWARF4=y - -# Some important information in VMCOREINFO is initialized in the kexec code for -# some reason. -CONFIG_KEXEC=y - -# In case we need to refer to the kernel config in the future. -CONFIG_IKCONFIG=y -CONFIG_IKCONFIG_PROC=y -""" - - DROPBOX_API_URL = "https://api.dropboxapi.com" CONTENT_API_URL = "https://content.dropboxapi.com" -def humanize_size(n, precision=1): +def humanize_size(n: SupportsFloat, precision: int = 1) -> str: n = float(n) for unit in ["", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi"]: if abs(n) < 1024: @@ -88,19 +58,23 @@ def humanize_size(n, precision=1): return f"{n:.{precision}f}{unit}B" -def humanize_duration(seconds): +def humanize_duration(seconds: SupportsRound[Any]) -> str: seconds = round(seconds) return f"{seconds // 60}m{seconds % 60}s" -# Like aiohttp.ClientResponse.raise_for_status(), but includes the response -# body. -async def raise_for_status_body(resp): +async def raise_for_status_body(resp: aiohttp.ClientResponse) -> None: + """ + Like aiohttp.ClientResponse.raise_for_status(), but includes the response + body. + """ if resp.status >= 400: - message = resp.reason + message = resp.reason or "" body = await resp.text() if body: - message += ": " + body + if message: + message += ": " + message += body raise aiohttp.ClientResponseError( resp.request_info, resp.history, @@ -110,11 +84,17 @@ async def raise_for_status_body(resp): ) -async def get_kernel_org_releases(http_client): +def get_current_localversion() -> str: + with open(os.path.join(os.path.dirname(__file__), "config"), "r") as f: + match = re.search(r'^CONFIG_LOCALVERSION="([^"]*)"', f.read(), re.MULTILINE) + return match.group(1) if match else "" + + +async def get_kernel_org_versions(http_client: aiohttp.ClientSession) -> List[str]: async with http_client.get(KERNEL_ORG_JSON, raise_for_status=True) as resp: releases = (await resp.json())["releases"] return [ - "v" + release["version"] + release["version"] for release in releases if release["moniker"] in {"mainline", "stable", "longterm"} # 3.16 seems to be missing "x86/build/64: Force the linker to use @@ -125,28 +105,27 @@ async def get_kernel_org_releases(http_client): ] -async def get_available_kernel_releases(http_client, token): +async def get_available_kernel_releases( + http_client: aiohttp.ClientSession, token: str +) -> Set[str]: headers = {"Authorization": "Bearer " + token} params = {"path": "/Public/x86_64"} url = DROPBOX_API_URL + "/2/files/list_folder" available = set() while True: async with http_client.post(url, headers=headers, json=params) as resp: + if resp.status == 409 and (await resp.json())["error_summary"].startswith( + "path/not_found/" + ): + break + await raise_for_status_body(resp) obj = await resp.json() for entry in obj["entries"]: if entry[".tag"] != "file": continue - match = re.fullmatch( - r"vmlinux-(\d+)\.(\d+)\.(\d+)(-rc\d+)?\.zst", entry["name"] - ) - if not match: - continue - version = f"v{match.group(1)}.{match.group(2)}" - if match.group(3) != "0": - version += "." + match.group(3) - if match.group(4): - version += match.group(4) - available.add(version) + match = re.fullmatch(r"vmlinux-(.*)\.zst", entry["name"]) + if match: + available.add(match.group(1)) if not obj["has_more"]: break url = DROPBOX_API_URL + "/2/files/list_folder/continue" @@ -154,7 +133,7 @@ async def get_available_kernel_releases(http_client, token): return available -async def check_call(*args, **kwds): +async def check_call(*args: Any, **kwds: Any) -> None: proc = await asyncio.create_subprocess_exec(*args, **kwds) returncode = await proc.wait() if returncode != 0: @@ -164,10 +143,9 @@ async def check_call(*args, **kwds): ) -async def check_output(*args, **kwds): - proc = await asyncio.create_subprocess_exec( - *args, **kwds, stdout=asyncio.subprocess.PIPE - ) +async def check_output(*args: Any, **kwds: Any) -> bytes: + kwds["stdout"] = asyncio.subprocess.PIPE + proc = await asyncio.create_subprocess_exec(*args, **kwds) stdout = (await proc.communicate())[0] if proc.returncode != 0: command = " ".join(shlex.quote(arg) for arg in args) @@ -177,17 +155,27 @@ async def check_output(*args, **kwds): return stdout -async def compress_file(in_path, out_path, *args, **kwds): +async def compress_file(in_path: str, out_path: str, **kwds: Any) -> None: logger.info("compressing %r", in_path) start = time.monotonic() - await check_call("zstd", "-T0", "-19", "-q", in_path, "-o", out_path, *args, **kwds) + await check_call("zstd", "-T0", "-19", "-q", in_path, "-o", out_path, **kwds) elapsed = time.monotonic() - start logger.info("compressed %r in %s", in_path, humanize_duration(elapsed)) -def getpwd(): - # This is how GCC determines the working directory. See - # https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libiberty/getpwd.c;hb=HEAD +async def post_process_vmlinux(vmlinux: str, **kwds: Any) -> None: + logger.info("removing relocations from %r", vmlinux) + await check_call( + "objcopy", "--remove-relocations=*", vmlinux, vmlinux + ".norel", **kwds + ) + await compress_file(vmlinux + ".norel", vmlinux + ".zst") + + +def getpwd() -> str: + """ + Get the current working directory in the same way that GCC does. See + https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libiberty/getpwd.c;hb=HEAD. + """ try: pwd = os.environ["PWD"] if pwd.startswith("/"): @@ -200,13 +188,21 @@ def getpwd(): return os.getcwd() -async def build_kernel(commit, build_dir, log_file): +async def build_kernel( + commit: str, build_dir: str, log_file: TextIO +) -> Tuple[str, str]: + """ + Returns built kernel release (i.e., `uname -r`) and image name (e.g., + `arch/x86/boot/bzImage`). + """ await check_call( "git", "checkout", commit, stdout=log_file, stderr=asyncio.subprocess.STDOUT ) - with open(os.path.join(build_dir, ".config"), "w") as config_file: - config_file.write(DEFCONFIG) + shutil.copy( + os.path.join(os.path.dirname(__file__), "config"), + os.path.join(build_dir, ".config"), + ) logger.info("building %s", commit) start = time.monotonic() @@ -218,7 +214,7 @@ async def build_kernel(commit, build_dir, log_file): "KCFLAGS=" + cflags, "O=" + build_dir, "-j", - str(multiprocessing.cpu_count()), + str(nproc()), ] await check_call( "make", @@ -234,20 +230,21 @@ async def build_kernel(commit, build_dir, log_file): vmlinux = os.path.join(build_dir, "vmlinux") release, image_name = ( await asyncio.gather( - compress_file( - vmlinux, - vmlinux + ".zst", - stdout=log_file, - stderr=asyncio.subprocess.STDOUT, + post_process_vmlinux( + vmlinux, stdout=log_file, stderr=asyncio.subprocess.STDOUT ), check_output("make", *kbuild_args, "-s", "kernelrelease", stderr=log_file), check_output("make", *kbuild_args, "-s", "image_name", stderr=log_file), ) )[1:] - return build_dir, release.decode().strip(), image_name.decode().strip() + return release.decode().strip(), image_name.decode().strip() -async def try_build_kernel(commit): +async def try_build_kernel(commit: str) -> Optional[Tuple[str, str, str]]: + """ + Returns build directory, kernel release, and image name on success, None on + error. + """ proc = await asyncio.create_subprocess_exec( "git", "rev-parse", @@ -267,7 +264,8 @@ async def try_build_kernel(commit): os.mkdir(build_dir, 0o755) with open(log_path, "w") as log_file: try: - return await build_kernel(commit, build_dir, log_file) + release, image_name = await build_kernel(commit, build_dir, log_file) + return build_dir, release, image_name except Exception: logger.exception("building %s failed; see %r", commit, log_path) return None @@ -279,12 +277,12 @@ async def try_build_kernel(commit): class Uploader: CHUNK_SIZE = 8 * 1024 * 1024 - def __init__(self, http_client, token): + def __init__(self, http_client: aiohttp.ClientSession, token: str) -> None: self._http_client = http_client self._token = token - self._pending = [] + self._pending: List[Tuple[str, asyncio.Task[bool]]] = [] - async def _upload_file_obj(self, file, commit): + async def _upload_file_obj(self, file: BinaryIO, commit: Dict[str, Any]) -> None: headers = { "Authorization": "Bearer " + self._token, "Content-Type": "application/octet-stream", @@ -320,7 +318,9 @@ async def _upload_file_obj(self, file, commit): if last: break - async def _try_upload_file_obj(self, file, commit): + async def _try_upload_file_obj( + self, file: BinaryIO, commit: Dict[str, Any] + ) -> bool: try: logger.info("uploading %r", commit["path"]) start = time.monotonic() @@ -332,7 +332,7 @@ async def _try_upload_file_obj(self, file, commit): logger.exception("uploading %r failed", commit["path"]) return False - async def _try_upload_file(self, path, commit): + async def _try_upload_file(self, path: str, commit: Dict[str, Any]) -> bool: try: logger.info("uploading %r to %r", path, commit["path"]) start = time.monotonic() @@ -351,25 +351,31 @@ async def _try_upload_file(self, path, commit): return False @staticmethod - def _make_commit(dst_path, *, mode=None, autorename=None): - commit = {"path": dst_path} + def _make_commit( + dst_path: str, *, mode: Optional[str] = None, autorename: Optional[bool] = None + ) -> Dict[str, Any]: + commit: Dict[str, Any] = {"path": dst_path} if mode is not None: commit["mode"] = mode if autorename is not None: commit["autorename"] = autorename return commit - def queue_file_obj(self, file, *args, **kwds): + def queue_file_obj(self, file: BinaryIO, *args: Any, **kwds: Any) -> None: commit = self._make_commit(*args, **kwds) task = asyncio.create_task(self._try_upload_file_obj(file, commit)) self._pending.append((commit["path"], task)) - def queue_file(self, src_path, *args, **kwds): + def queue_file(self, src_path: str, *args: Any, **kwds: Any) -> None: commit = self._make_commit(*args, **kwds) task = asyncio.create_task(self._try_upload_file(src_path, commit)) self._pending.append((commit["path"], task)) - async def wait(self): + async def wait(self) -> Tuple[List[str], List[str]]: + """ + Returns list of successfully uploaded paths and list of paths that + failed to upload. + """ succeeded = [] failed = [] for path, task in self._pending: @@ -381,10 +387,16 @@ async def wait(self): return succeeded, failed -# The Dropbox API doesn't provide a way to get the links for entries inside of -# a shared folder, so we're forced to scrape them from the webpage and XHR -# endpoint. -async def list_shared_folder(http_client, url): +async def list_shared_folder( + http_client: aiohttp.ClientSession, url: str +) -> AsyncGenerator[Tuple[str, bool, str], None]: + """ + List a Dropbox shared folder. The Dropbox API doesn't provide a way to get + the links for entries inside of a shared folder, so we're forced to scrape + them from the webpage and XHR endpoint. + + Generates filename, whether it is a directory, and its shared link. + """ method = "GET" data = None while True: @@ -394,6 +406,7 @@ async def list_shared_folder(http_client, url): match = re.search( r'"\{\\"shared_link_infos\\".*[^\\]\}"', (await resp.text()) ) + assert match obj = json.loads(json.loads(match.group())) else: await raise_for_status_body(resp) @@ -406,16 +419,23 @@ async def list_shared_folder(http_client, url): method = "POST" url = "https://www.dropbox.com/list_shared_link_folder_entries" data = { - "t": http_client.cookie_jar.filter_cookies(url)["t"].value, + "t": http_client.cookie_jar.filter_cookies(URL(url))["t"].value, "link_key": obj["folder_share_token"]["linkKey"], "link_type": obj["folder_share_token"]["linkType"], "secure_hash": obj["folder_share_token"]["secureHash"], "sub_path": obj["folder_share_token"]["subPath"], } + assert data is not None data["voucher"] = obj["next_request_voucher"] -async def walk_shared_folder(http_client, url): +async def walk_shared_folder( + http_client: aiohttp.ClientSession, url: str +) -> AsyncGenerator[Tuple[str, List[Tuple[str, str]], List[Tuple[str, str]]], None]: + """ + Walk a Dropbox shared folder, similar to os.walk(). Generates path, list of + files and their shared links, and list of folders and their shared links. + """ stack = [("", url)] while stack: path, url = stack.pop() @@ -432,7 +452,7 @@ async def walk_shared_folder(http_client, url): stack.extend((path + filename, href) for filename, href in dirs) -def make_download_url(url): +def make_download_url(url: str) -> str: parsed = urllib.parse.urlsplit(url) query = [ (name, value) @@ -443,7 +463,9 @@ def make_download_url(url): return urllib.parse.urlunsplit(parsed._replace(query=urllib.parse.urlencode(query))) -async def update_index(http_client, token, uploader): +async def update_index( + http_client: aiohttp.ClientSession, token: str, uploader: Uploader +) -> bool: try: logger.info("finding shared folder link") headers = {"Authorization": "Bearer " + token} @@ -505,7 +527,7 @@ async def update_index(http_client, token, uploader): return False -async def main(): +async def main() -> None: logging.basicConfig( format="%(asctime)s:%(levelname)s:%(name)s:%(message)s", level=logging.INFO ) @@ -551,7 +573,7 @@ async def main(): ): sys.exit("-b/-k must be run from linux.git") - if args.upload or args.upload_files or args.index: + if args.build_kernel_org or args.upload or args.upload_files or args.index: if os.isatty(sys.stdin.fileno()): dropbox_token = getpass.getpass("Enter Dropbox app API token: ") else: @@ -564,21 +586,37 @@ async def main(): async with aiohttp.ClientSession(trust_env=True) as http_client: # dict rather than set to preserve insertion order. - to_build = {build: True for build in (args.build or ())} + to_build = dict.fromkeys(args.build or ()) if args.build_kernel_org: + localversion = get_current_localversion() + logger.info("current localversion: %s", localversion) try: + # In this context, "version" is a tag name without the "v" + # prefix and "release" is a uname release string. logger.info( - "getting list of kernel.org releases and available releases" + "getting list of kernel.org versions and available releases" ) kernel_org, available = await asyncio.gather( - get_kernel_org_releases(http_client), + get_kernel_org_versions(http_client), get_available_kernel_releases(http_client, dropbox_token), ) - logger.info("kernel.org releases: %s", ", ".join(kernel_org)) + logger.info("kernel.org versions: %s", ", ".join(kernel_org)) logger.info("available releases: %s", ", ".join(sorted(available))) - for kernel in kernel_org: - if kernel not in available: - to_build[kernel] = True + for version in kernel_org: + match = re.fullmatch(r"(\d+\.\d+)(\.\d+)?(-rc\d+)?", version) + if not match: + logger.error("couldn't parse kernel.org version %r", version) + sys.exit(1) + release = "".join( + [ + match.group(1), + match.group(2) or ".0", + match.group(3) or "", + localversion, + ] + ) + if release not in available: + to_build["v" + version] = None except Exception: logger.exception( "failed to get kernel.org releases and/or available releases" diff --git a/vmtest/onoatimehack.c b/vmtest/onoatimehack.c new file mode 100644 index 000000000..3d65f51cf --- /dev/null +++ b/vmtest/onoatimehack.c @@ -0,0 +1,105 @@ +// Copyright 2020 - Omar Sandoval +// SPDX-License-Identifier: GPL-3.0+ + +/* + * QEMU's 9pfs server passes through O_NOATIME from the client. If the server + * process doesn't have permission to use O_NOATIME (e.g., because it's being + * run without privileges and it doesn't own the file), then the open will fail. + * Overlayfs uses O_NOATIME, so overlayfs on top of 9pfs doesn't work. We work + * around this with this LD_PRELOAD hack to remove O_NOATIME from open() and + * fcntl() calls. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#define ORIG(name) ({ \ + static typeof(&name) orig; \ + \ + if (!orig) { \ + void *tmp; \ + \ + tmp = dlsym(RTLD_NEXT, #name); \ + if (!tmp) { \ + fprintf(stderr, "%s\n", dlerror()); \ + abort(); \ + } \ + orig = tmp; \ + } \ + orig; \ +}) + +#ifndef __OPEN_NEEDS_MODE +/* From glibc fnctl.h. */ +#ifdef __O_TMPFILE +# define __OPEN_NEEDS_MODE(oflag) \ + (((oflag) & O_CREAT) != 0 || ((oflag) & __O_TMPFILE) == __O_TMPFILE) +#else +# define __OPEN_NEEDS_MODE(oflag) (((oflag) & O_CREAT) != 0) +#endif +#endif + +#define OPEN_MODE(flags) ({ \ + mode_t mode = 0; \ + \ + if (__OPEN_NEEDS_MODE(flags)) { \ + va_list ap; \ + \ + va_start(ap, flags); \ + mode = va_arg(ap, mode_t); \ + va_end(ap); \ + } \ + mode; \ +}) + +int open(const char *pathname, int flags, ...) +{ + flags &= ~O_NOATIME; + return ORIG(open)(pathname, flags, OPEN_MODE(flags)); +} + +int open64(const char *pathname, int flags, ...) +{ + flags &= ~O_NOATIME; + return ORIG(open64)(pathname, flags, OPEN_MODE(flags)); +} + +int openat(int dirfd, const char *pathname, int flags, ...) +{ + flags &= ~O_NOATIME; + return ORIG(openat)(dirfd, pathname, flags, OPEN_MODE(flags)); +} + +int openat64(int dirfd, const char *pathname, int flags, ...) +{ + flags &= ~O_NOATIME; + return ORIG(openat64)(dirfd, pathname, flags, OPEN_MODE(flags)); +} + +#define FCNTL_ARG(cmd) ({ \ + va_list ap; \ + void *arg; \ + \ + va_start(ap, cmd); \ + arg = va_arg(ap, void *); \ + va_end(ap); \ + if (cmd == F_SETFL) \ + arg = (void *)((uintptr_t)arg & ~O_NOATIME); \ + arg; \ +}) + +int fcntl(int fd, int cmd, ...) +{ + return ORIG(fcntl)(fd, cmd, FCNTL_ARG(cmd)); +} + +int fcntl64(int fd, int cmd, ...) +{ + return ORIG(fcntl64)(fd, cmd, FCNTL_ARG(cmd)); +} diff --git a/vmtest/resolver.py b/vmtest/resolver.py new file mode 100644 index 000000000..bf2f8fa84 --- /dev/null +++ b/vmtest/resolver.py @@ -0,0 +1,173 @@ +# Copyright 2020 - Omar Sandoval +# SPDX-License-Identifier: GPL-3.0+ + +import fnmatch +import glob +import os +import os.path +import queue +import re +import shutil +import subprocess +import threading +from typing import Any, Dict, Iterator, NamedTuple, Optional, Sequence, Union +import urllib.request + +from util import KernelVersion + + +# This URL contains a mapping from file names to URLs where those files can be +# downloaded. This is needed because the files under a Dropbox shared folder +# have randomly-generated links. +_INDEX_URL = "https://www.dropbox.com/sh/2mcf2xvg319qdaw/AAC_AbpvQPRrHF-99B2REpXja/x86_64/INDEX?dl=1" + + +class ResolvedKernel(NamedTuple): + release: str + vmlinux: str + vmlinuz: str + + +class KernelResolver: + def __init__(self, kernels: Sequence[str], download_dir: str) -> None: + self._kernels = kernels + self._arch_download_dir = os.path.join(download_dir, "x86_64") + self._cached_index: Optional[Dict[str, str]] = None + self._index_lock = threading.Lock() + self._queue: queue.Queue[Union[ResolvedKernel, Exception, None]] = queue.Queue() + self._thread: Optional[threading.Thread] + # Don't create the thread if we don't have anything to do. + if kernels: + self._thread = threading.Thread(target=self._resolve_all, daemon=True) + self._thread.start() + else: + self._thread = None + self._queue.put(None) + + def __enter__(self) -> "KernelResolver": + return self + + def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None: + if self._thread: + self._thread.join() + + def _resolve_build(self, path: str) -> ResolvedKernel: + release = subprocess.check_output( + ["make", "-s", "kernelrelease"], universal_newlines=True, cwd=path, + ).strip() + vmlinuz = subprocess.check_output( + ["make", "-s", "image_name"], universal_newlines=True, cwd=path, + ).strip() + return ResolvedKernel( + release=release, + vmlinux=os.path.join(path, "vmlinux"), + vmlinuz=os.path.join(path, vmlinuz), + ) + + @property + def _index(self) -> Dict[str, str]: + if self._cached_index is None: + with self._index_lock: + if self._cached_index is None: + index = {} + with urllib.request.urlopen(_INDEX_URL) as u: + for line in u: + name, url = line.decode().rstrip("\n").split("\t", 1) + index[name] = url + self._cached_index = index + return self._cached_index + + def _find_kernel(self, pattern: str) -> str: + matches = [] + for name, url in self._index.items(): + match = re.fullmatch(r"vmlinux-(.*)\.zst", name) + if match and fnmatch.fnmatch(match.group(1), pattern): + matches.append(match.group(1)) + if not matches: + raise Exception(f"no kernel release matches {pattern!r}") + return max(matches, key=KernelVersion) + + def _download_file(self, name: str, *, compressed: bool = False) -> str: + path = os.path.join(self._arch_download_dir, name) + if not os.path.exists(path): + dir = os.path.dirname(path) + os.makedirs(dir, exist_ok=True) + with open(os.open(dir, os.O_WRONLY | os.O_TMPFILE), "wb") as f: + if compressed: + name += ".zst" + with urllib.request.urlopen(self._index[name]) as u: + if compressed: + with subprocess.Popen( + ["zstd", "-d", "-", "--stdout"], + stdin=subprocess.PIPE, + stdout=f, + ) as proc: + assert proc.stdin is not None + shutil.copyfileobj(u, proc.stdin) + if proc.returncode != 0: + raise subprocess.CalledProcessError( + proc.returncode, proc.args + ) + else: + shutil.copyfileobj(u, f) + # Passing dst_dir_fd forces Python to use linkat() with + # AT_SYMLINK_FOLLOW instead of link(). See + # https://bugs.python.org/msg348086. + dir_fd = os.open(dir, os.O_RDONLY | os.O_DIRECTORY) + try: + os.link( + f"/proc/self/fd/{f.fileno()}", + os.path.basename(path), + dst_dir_fd=dir_fd, + ) + finally: + os.close(dir_fd) + return path + + def _download(self, release: str) -> ResolvedKernel: + # Only do the wildcard lookup if the release is a wildcard + # pattern. + if release != glob.escape(release): + release = self._find_kernel(release) + vmlinux_path = self._download_file(f"vmlinux-{release}", compressed=True) + vmlinuz_path = self._download_file(f"vmlinuz-{release}") + return ResolvedKernel(release, vmlinux_path, vmlinuz_path) + + def _resolve_all(self) -> None: + try: + for kernel in self._kernels: + if kernel.startswith(".") or kernel.startswith("/"): + resolved = self._resolve_build(kernel) + else: + resolved = self._download(kernel) + self._queue.put(resolved) + self._queue.put(None) + except Exception as e: + self._queue.put(e) + + def __iter__(self) -> Iterator[ResolvedKernel]: + while True: + result = self._queue.get() + if isinstance(result, Exception): + raise result + elif result is None: + break + yield result + + +if __name__ == "__main__": + import argparse + + parser = argparse.ArgumentParser( + description="resolve and download vmtest kernels", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "-d", "--directory", default="build/vmtest", help="directory to download to" + ) + parser.add_argument("kernels", metavar="KERNEL", nargs="*") + args = parser.parse_args() + + with KernelResolver(args.kernels, args.directory) as resolver: + for kernel in resolver: + print(kernel) diff --git a/vmtest/vm.py b/vmtest/vm.py new file mode 100644 index 000000000..569457f25 --- /dev/null +++ b/vmtest/vm.py @@ -0,0 +1,285 @@ +# Copyright 2020 - Omar Sandoval +# SPDX-License-Identifier: GPL-3.0+ + +import errno +import os +import os.path +import shlex +import shutil +import socket +import subprocess +import tempfile + +from util import nproc, out_of_date + + +# Script run as init in the virtual machine. This only depends on busybox. We +# don't assume that any regular commands are built in (not even echo or test), +# so we always explicitly run busybox. +_INIT_TEMPLATE = r"""#!{busybox} sh + +set -eu + +export BUSYBOX={busybox} +HOSTNAME=vmtest +VPORT_NAME=com.osandov.vmtest.0 +# Set up overlayfs on the temporary directory containing this script. +mnt=$(dirname "$0") + +trap '$BUSYBOX poweroff -f' EXIT + +"$BUSYBOX" mount -t tmpfs tmpfs "$mnt" +"$BUSYBOX" mkdir -m 755 "$mnt/upper" "$mnt/work" "$mnt/merged" + +"$BUSYBOX" mkdir -m 755 "$mnt/upper/dev" "$mnt/upper/etc" "$mnt/upper/mnt" +"$BUSYBOX" mkdir -m 555 "$mnt/upper/proc" "$mnt/upper/sys" +"$BUSYBOX" mkdir -m 1777 "$mnt/upper/tmp" + +"$BUSYBOX" cat << EOF > "$mnt/upper/etc/hosts" +127.0.0.1 localhost +::1 localhost +127.0.1.1 $HOSTNAME.localdomain $HOSTNAME +EOF +: > "$mnt/upper/etc/resolv.conf" + +"$BUSYBOX" mount -t overlay -o lowerdir=/,upperdir="$mnt/upper",workdir="$mnt/work" overlay "$mnt/merged" +"$BUSYBOX" pivot_root "$mnt/merged" "$mnt/merged/mnt" +cd / +"$BUSYBOX" umount -l /mnt + +"$BUSYBOX" mount -t devtmpfs -o nosuid,noexec dev /dev +"$BUSYBOX" mount -t proc -o nosuid,nodev,noexec proc /proc +"$BUSYBOX" mount -t sysfs -o nosuid,nodev,noexec sys /sys +# Ideally we'd just be able to create an opaque directory for /tmp on the upper +# layer. However, before Linux kernel commit 51f7e52dc943 ("ovl: share inode +# for hard link") (in v4.8), overlayfs doesn't handle hard links correctly, +# which breaks some tests. +"$BUSYBOX" mount -t tmpfs -o nosuid,nodev tmpfs /tmp + +"$BUSYBOX" hostname "$HOSTNAME" +"$BUSYBOX" ip link set lo up + +vport= +for vport_dir in /sys/class/virtio-ports/*; do + if "$BUSYBOX" [ -r "$vport_dir/name" \ + -a "$("$BUSYBOX" cat "$vport_dir/name")" = "$VPORT_NAME" ]; then + vport="${{vport_dir#/sys/class/virtio-ports/}}" + break + fi +done +if "$BUSYBOX" [ -z "$vport" ]; then + "$BUSYBOX" echo "could not find virtio-port \"$VPORT_NAME\"" + exit 1 +fi + +set +e +"$BUSYBOX" sh -c {command} +rc=$? +set -e + +"$BUSYBOX" echo "Exited with status $rc" +"$BUSYBOX" echo "$rc" > "/dev/$vport" +""" + + +def install_vmlinux_precommand(command: str, vmlinux: str) -> str: + vmlinux = shlex.quote(os.path.abspath(vmlinux)) + return fr""""$BUSYBOX" mkdir -m 755 -p /boot && + release=$("$BUSYBOX" uname -r) && + "$BUSYBOX" ln -sf {vmlinux} "/boot/vmlinux-$release" && + {command}""" + + +def _compile( + *args: str, + CPPFLAGS: str = "", + CFLAGS: str = "", + LDFLAGS: str = "", + LIBADD: str = "", +) -> None: + # This mimics automake: the order of the arguments allows for the default + # flags to be overridden by environment variables, and we use the same + # default CFLAGS. + cmd = [ + os.getenv("CC", "cc"), + *shlex.split(CPPFLAGS), + *shlex.split(os.getenv("CPPFLAGS", "")), + *shlex.split(CFLAGS), + *shlex.split(os.getenv("CFLAGS", "-g -O2")), + *shlex.split(LDFLAGS), + *shlex.split(os.getenv("LDFLAGS", "")), + *args, + *shlex.split(LIBADD), + *shlex.split(os.getenv("LIBS", "")), + ] + print(" ".join([shlex.quote(arg) for arg in cmd])) + subprocess.check_call(cmd) + + +def _build_onoatimehack(dir: str) -> str: + os.makedirs(dir, exist_ok=True) + + onoatimehack_so = os.path.join(dir, "onoatimehack.so") + onoatimehack_c = os.path.relpath( + os.path.join(os.path.dirname(__file__), "onoatimehack.c") + ) + if out_of_date(onoatimehack_so, onoatimehack_c): + _compile( + "-o", + onoatimehack_so, + onoatimehack_c, + CPPFLAGS="-D_GNU_SOURCE", + CFLAGS="-fPIC", + LDFLAGS="-shared", + LIBADD="-ldl", + ) + return onoatimehack_so + + +class LostVMError(Exception): + pass + + +def run_in_vm(command: str, *, vmlinuz: str, build_dir: str) -> int: + # multidevs was added in QEMU 4.2.0. + if ( + "multidevs" + in subprocess.run( + ["qemu-system-x86_64", "-help"], + stdout=subprocess.PIPE, + universal_newlines=True, + ).stdout + ): + multidevs = ",multidevs=remap" + else: + multidevs = "" + + onoatimehack = _build_onoatimehack(build_dir) + + with tempfile.TemporaryDirectory(prefix="drgn-vmtest-") as temp_dir, socket.socket( + socket.AF_UNIX + ) as server_sock: + socket_path = os.path.join(temp_dir, "socket") + server_sock.bind(socket_path) + server_sock.listen() + + busybox = shutil.which("busybox") + if busybox is None: + raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), "busybox") + init = os.path.abspath(os.path.join(temp_dir, "init")) + with open(init, "w") as init_file: + init_file.write( + _INIT_TEMPLATE.format( + busybox=shlex.quote(busybox), command=shlex.quote(command) + ) + ) + os.chmod(init, 0o755) + with subprocess.Popen( + [ + # fmt: off + "qemu-system-x86_64", "-cpu", "host", "-enable-kvm", + + "-smp", str(nproc()), "-m", "2G", + + "-nodefaults", "-display", "none", "-serial", "mon:stdio", + + # This along with -append panic=-1 ensures that we exit on a + # panic instead of hanging. + "-no-reboot", + + "-virtfs", + f"local,id=root,path=/,mount_tag=/dev/root,security_model=none,readonly{multidevs}", + + "-device", "virtio-serial", + "-chardev", f"socket,id=vmtest,path={socket_path}", + "-device", + "virtserialport,chardev=vmtest,name=com.osandov.vmtest.0", + + "-kernel", vmlinuz, + "-append", + f"rootfstype=9p rootflags=trans=virtio,cache=loose ro console=0,115200 panic=-1 init={init}", + # fmt: on + ], + env={ + **os.environ, + "LD_PRELOAD": f"{onoatimehack}:{os.getenv('LD_PRELOAD', '')}", + }, + ) as qemu: + server_sock.settimeout(5) + try: + sock = server_sock.accept()[0] + except socket.timeout: + raise LostVMError( + f"QEMU did not connect within {server_sock.gettimeout()} seconds" + ) + try: + status_buf = bytearray() + while True: + try: + buf = sock.recv(4) + except ConnectionResetError: + buf = b"" + if not buf: + break + status_buf.extend(buf) + finally: + sock.close() + if not status_buf: + raise LostVMError("VM did not return status") + if status_buf[-1] != ord("\n") or not status_buf[:-1].isdigit(): + raise LostVMError(f"VM returned invalid status: {repr(status_buf)[11:-1]}") + return int(status_buf) + + +if __name__ == "__main__": + import argparse + import sys + + from vmtest.resolver import KernelResolver + + parser = argparse.ArgumentParser( + description="run vmtest virtual machine", + formatter_class=argparse.ArgumentDefaultsHelpFormatter, + ) + parser.add_argument( + "-d", + "--directory", + default="build/vmtest", + help="directory for build artifacts and downloaded kernels", + ) + parser.add_argument( + "--lost-status", + metavar="STATUS", + type=int, + default=128, + help="exit status if VM is lost", + ) + parser.add_argument( + "-k", + "--kernel", + default=argparse.SUPPRESS, + help="kernel to use (default: latest available kernel)", + ) + parser.add_argument( + "command", + type=str, + nargs=argparse.REMAINDER, + help="command to run in VM (default: sh -i)", + ) + args = parser.parse_args() + + with KernelResolver( + [getattr(args, "kernel", "*")], download_dir=args.directory + ) as resolver: + kernel = next(iter(resolver)) + try: + command = " ".join(args.command) if args.command else '"$BUSYBOX" sh -i' + command = install_vmlinux_precommand(command, kernel.vmlinux) + sys.exit( + run_in_vm( + command=command, vmlinuz=kernel.vmlinuz, build_dir=args.directory + ) + ) + except LostVMError as e: + print("error:", e, file=sys.stderr) + sys.exit(args.lost_status)