Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 236 lines (198 sloc) 5.571 kb
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
1 #include <dwarf.h>
2e7895eb »
2011-07-07 Identity zipper
2 #include <err.h>
3 #include <fcntl.h>
4094932e »
2011-07-07 Add main of dwarfzip
4 #include <stdio.h>
5 #include <stdlib.h>
2e7895eb »
2011-07-07 Identity zipper
6 #include <string.h>
7 #include <sys/mman.h>
8 #include <sys/stat.h>
9 #include <sys/types.h>
10 #include <unistd.h>
4094932e »
2011-07-07 Add main of dwarfzip
11
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
12 #include <map>
4094932e »
2011-07-07 Add main of dwarfzip
13 #include <memory>
2e7895eb »
2011-07-07 Identity zipper
14 #include <vector>
4094932e »
2011-07-07 Add main of dwarfzip
15
16 #include "binary.h"
2e7895eb »
2011-07-07 Identity zipper
17 #include "scanner.h"
4094932e »
2011-07-07 Add main of dwarfzip
18
19 using namespace std;
20
2e7895eb »
2011-07-07 Identity zipper
21 static void uleb128o(uint64_t v, uint8_t*& p) {
22 do {
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
23 uint8_t b = v & 0x7f;
2e7895eb »
2011-07-07 Identity zipper
24 v >>= 7;
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
25 if (v)
26 b |= 0x80;
27 *p++ = b;
2e7895eb »
2011-07-07 Identity zipper
28 } while (v);
29 }
30
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
31 static void sleb128o(int64_t v, uint8_t*& p) {
32 bool done = false;
33 while (!done) {
34 uint8_t b = v & 0x7f;
35 v >>= 7;
36 if ((v == 0 && (b & 0x40) == 0) || (v == -1 && (b & 0x40))) {
37 done = true;
38 } else {
39 b |= 0x80;
40 }
41 *p++ = b;
42 }
43 }
44
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
45 static bool opt_d = false;
46
2e7895eb »
2011-07-07 Identity zipper
47 class ZipScanner : public Scanner {
48 public:
49 ZipScanner(Binary* binary, uint8_t* out)
50 : Scanner(binary),
51 p_(out),
625fa6e2 »
2011-07-07 Remove stat code from zipper
52 last_offset_(0),
f901dbef »
2011-07-09 Compress DW_FORM_addr as well
53 cu_(NULL),
625fa6e2 »
2011-07-07 Remove stat code from zipper
54 cu_cnt_(0) {
2e7895eb »
2011-07-07 Identity zipper
55 }
56
57 const uint8_t* cur() const {
58 return p_;
59 }
60
61 private:
62 virtual void onCU(CU* cu, uint64_t offset) {
63 fprintf(stderr, "CU: %d @0x%lx len=%x version=%x ptrsize=%x\n",
625fa6e2 »
2011-07-07 Remove stat code from zipper
64 cu_cnt_, last_offset_, cu->length, cu->version, cu->ptrsize);
2e7895eb »
2011-07-07 Identity zipper
65
66 memcpy(p_, cu, sizeof(CU));
67 p_ += sizeof(CU);
68
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
69 last_values_.clear();
70
f901dbef »
2011-07-09 Compress DW_FORM_addr as well
71 cu_ = cu;
625fa6e2 »
2011-07-07 Remove stat code from zipper
72 cu_cnt_++;
2e7895eb »
2011-07-07 Identity zipper
73 last_offset_ = offset;
74 }
75
76 virtual void onAbbrev(uint64_t number, uint64_t offset) {
77 uleb128o(number, p_);
78
79 //fprintf(stderr, "abbr %lu @%lx\n", number, last_offset_);
80 last_offset_ = offset;
81 }
82
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
83 virtual void onAttr(uint16_t name, uint8_t form, uint64_t value,
84 uint64_t offset) {
85 switch (form) {
f901dbef »
2011-07-09 Compress DW_FORM_addr as well
86 case DW_FORM_addr:
87 case DW_FORM_ref_addr: {
88 if (cu_->ptrsize != 8)
89 break;
90
91 if (opt_d) {
92 map<int, uint64_t>::iterator iter =
93 last_values_.insert(make_pair(name, 0)).first;
94 int64_t v = iter->second + value;
95 int64_t* op = (int64_t*)p_;
96 *op = v;
97 p_ += 8;
98 iter->second = v;
99 } else {
100 map<int, uint64_t>::iterator iter =
101 last_values_.insert(make_pair(name, 0)).first;
102 int64_t diff = value - iter->second;
103 sleb128o(diff, p_);
104 iter->second = value;
105 }
106 break;
107 }
108
18b0a81e »
2011-07-09 Can scan zipped dwarf
109 case DW_FORM_strp:
110 case DW_FORM_data4:
111 case DW_FORM_ref4: {
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
112 if (opt_d) {
113 map<int, uint64_t>::iterator iter =
114 last_values_.insert(make_pair(name, 0)).first;
115 int32_t v = (static_cast<int32_t>(iter->second) +
116 static_cast<int32_t>(value));
117 int32_t* op = (int32_t*)p_;
118 *op = v;
119 p_ += 4;
120 iter->second = v;
121 } else {
122 int32_t v = static_cast<int32_t>(value);
123 map<int, uint64_t>::iterator iter =
124 last_values_.insert(make_pair(name, 0)).first;
125 int32_t diff = v - static_cast<int32_t>(iter->second);
126 sleb128o(diff, p_);
127 iter->second = v;
128 }
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
129 break;
130 }
131
132 default: {
133 size_t sz = offset - last_offset_;
134 memcpy(p_, binary_->debug_info + last_offset_, sz);
135 p_ += sz;
136 }
137 }
2e7895eb »
2011-07-07 Identity zipper
138
139 //fprintf(stderr, "attr %d %d @%lx\n", name, form, last_offset_);
140
141 last_offset_ = offset;
142 }
143
144 uint8_t* p_;
145 uint64_t last_offset_;
f901dbef »
2011-07-09 Compress DW_FORM_addr as well
146 CU* cu_;
625fa6e2 »
2011-07-07 Remove stat code from zipper
147 int cu_cnt_;
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
148 map<int, uint64_t> last_values_;
2e7895eb »
2011-07-07 Identity zipper
149 };
150
18b0a81e »
2011-07-09 Can scan zipped dwarf
151 static const int HEADER_SIZE = 8;
152
4094932e »
2011-07-07 Add main of dwarfzip
153 int main(int argc, char* argv[]) {
e3ddca66 »
2011-07-09 Handle -d option to decompress compressed binaries
154 const char* argv0 = argv[0];
155 for (int i = 1; i < argc; i++) {
156 if (argv[i][0] != '-') {
157 continue;
158 }
159 if (!strcmp(argv[i], "-d")) {
160 opt_d = true;
161 } else {
162 fprintf(stderr, "Unknown option: %s\n", argv[i]);
163 }
164 argc--;
165 argv++;
166 }
167
2e7895eb »
2011-07-07 Identity zipper
168 if (argc < 3) {
e3ddca66 »
2011-07-09 Handle -d option to decompress compressed binaries
169 fprintf(stderr, "Usage: %s [-d] binary output\n", argv0);
4094932e »
2011-07-07 Add main of dwarfzip
170 exit(1);
171 }
172
173 auto_ptr<Binary> binary(readBinary(argv[1]));
2e7895eb »
2011-07-07 Identity zipper
174
e3ddca66 »
2011-07-09 Handle -d option to decompress compressed binaries
175 if (opt_d && !binary->is_zipped) {
176 fprintf(stderr, "%s is not compressed\n", argv[1]);
177 exit(1);
178 } else if (!opt_d && binary->is_zipped) {
179 fprintf(stderr, "%s is already compressed\n", argv[1]);
180 exit(1);
181 }
182
2e7895eb »
2011-07-07 Identity zipper
183 int fd = open(argv[2], O_RDWR | O_CREAT | O_TRUNC, 0644);
184 if (fd < 0)
185 err(1, "open failed: %s", argv[1]);
186
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
187 if (!opt_d) {
188 if (write(fd, "\xdfZIP\0\0\0\0", HEADER_SIZE) < 0)
189 err(1, "write failed");
190 }
b30b6d96 »
2011-07-08 Output dwarfzip header
191
2e7895eb »
2011-07-07 Identity zipper
192 size_t debug_info_offset = binary->debug_info - binary->head;
193 if (write(fd, binary->head, debug_info_offset) < 0)
194 err(1, "write failed");
195
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
196 if (pwrite(fd, "", 1, binary->size + binary->reduced_size - 1) < 0)
2e7895eb »
2011-07-07 Identity zipper
197 err(1, "pwrite failed");
198
199 uint8_t* p = (uint8_t*)mmap(NULL, binary->mapped_size,
200 PROT_READ | PROT_WRITE, MAP_SHARED,
201 fd, 0);
202 if (p == MAP_FAILED)
203 err(1, "mmap failed");
204
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
205 ZipScanner zip(binary.get(),
206 p + debug_info_offset + (opt_d ? 0 : HEADER_SIZE));
2e7895eb »
2011-07-07 Identity zipper
207 zip.run();
208 fflush(stderr);
209
210 size_t out_size = zip.cur() - p;
211 if (lseek(fd, out_size, SEEK_SET) < 0)
212 err(1, "lseek failed");
213
214 const char* rest = binary->debug_info + binary->debug_info_len;
215 size_t rest_size = binary->size - (rest - binary->head);
216 if (write(fd, rest, rest_size) < 0)
217 err(1, "write failed");
218
219 out_size += rest_size;
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
220 if (opt_d)
221 out_size -= HEADER_SIZE;
2e7895eb »
2011-07-07 Identity zipper
222 if (ftruncate(fd, out_size) < 0)
223 err(1, "ftruncate failed");
224
83e2c82f »
2011-07-09 Now dwarfzip can decompress compressed binaries
225 if (!opt_d) {
226 uint32_t* offset_outp = (uint32_t*)(p + 4);
227 *offset_outp = binary->size - out_size + HEADER_SIZE;
228 }
b30b6d96 »
2011-07-08 Output dwarfzip header
229
230 munmap(p, binary->size);
2e7895eb »
2011-07-07 Identity zipper
231 close(fd);
232
b74ab2c7 »
2011-07-08 Simple compressor. 84.97% for chrome.
233 printf("%lu => %lu (%.2f%%)\n",
234 binary->size, out_size,
235 ((float)out_size / binary->size) * 100);
4094932e »
2011-07-07 Add main of dwarfzip
236 }
Something went wrong with that request. Please try again.