xref: /llvm-project/lldb/test/Shell/Register/Core/Inputs/strip-coredump.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1#!/usr/bin/env python
2# Strip unnecessary data from a core dump to reduce its size.
3#
4# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5# See https://llvm.org/LICENSE.txt for license information.
6# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7
8import argparse
9import os.path
10import sys
11import tempfile
12
13from elftools.elf.elffile import ELFFile
14
15
16def strip_non_notes(elf, inf, outf):
17    next_segment_offset = min(x.header.p_offset for x in elf.iter_segments())
18    copy_segments = filter(lambda x: x.header.p_type == "PT_NOTE", elf.iter_segments())
19
20    # first copy the headers
21    inf.seek(0)
22    outf.write(inf.read(next_segment_offset))
23
24    for seg in copy_segments:
25        assert seg.header.p_filesz > 0
26
27        inf.seek(seg.header.p_offset)
28        # fill the area between last write and new offset with zeros
29        outf.seek(seg.header.p_offset)
30
31        # now copy the segment
32        outf.write(inf.read(seg.header.p_filesz))
33
34
35def main():
36    argp = argparse.ArgumentParser()
37    action = argp.add_mutually_exclusive_group(required=True)
38    action.add_argument(
39        "--strip-non-notes",
40        action="store_const",
41        const=strip_non_notes,
42        dest="action",
43        help="Strip all segments except for notes",
44    )
45    argp.add_argument("elf", help="ELF file to strip (in place)", nargs="+")
46    args = argp.parse_args()
47
48    for path in args.elf:
49        with open(path, "rb") as f:
50            elf = ELFFile(f)
51            # we do not support copying the section table now
52            assert elf.num_sections() == 0
53
54            tmpf = tempfile.NamedTemporaryFile(dir=os.path.dirname(path), delete=False)
55            try:
56                args.action(elf, f, tmpf)
57            except:
58                os.unlink(tmpf.name)
59                raise
60            else:
61                os.rename(tmpf.name, path)
62
63    return 0
64
65
66if __name__ == "__main__":
67    sys.exit(main())
68