| 137 | |
| 138 | |
| 139 | Try<vector<Entry>> parse(const string& path) |
| 140 | { |
| 141 | // Read the complete file into a buffer |
| 142 | Try<string> buffer = os::read(path); |
| 143 | if (buffer.isError()) { |
| 144 | return Error(buffer.error()); |
| 145 | } |
| 146 | |
| 147 | const char* data = buffer->data(); |
| 148 | |
| 149 | // Grab a pointer to the old format header (for verification of |
| 150 | // HEADER_MAGIC_OLD later on). Then jump forward to the location of |
| 151 | // the new format header (it is the only format we support). |
| 152 | HeaderOld* headerOld = (HeaderOld*)data; |
| 153 | data += sizeof(HeaderOld); |
| 154 | if (data >= buffer->data() + buffer->size()) { |
| 155 | return Error("Invalid format"); |
| 156 | } |
| 157 | |
| 158 | data += headerOld->libraryCount * sizeof(EntryOld); |
| 159 | if (data >= buffer->data() + buffer->size()) { |
| 160 | return Error("Invalid format"); |
| 161 | } |
| 162 | |
| 163 | // The new format header and all of its library entries are embedded |
| 164 | // in the old format's string table (the current location of data). |
| 165 | // However, the header is aligned on an 8 byte boundary, so we |
| 166 | // need to align 'data' to get it to point to the new header. |
| 167 | data = align(data, alignof(HeaderNew)); |
| 168 | if (data >= buffer->data() + buffer->size()) { |
| 169 | return Error("Invalid format"); |
| 170 | } |
| 171 | |
| 172 | // Construct pointers to all of the important regions in the new |
| 173 | // format: the header, the libentry array, and the new string table |
| 174 | // (which starts at the same address as the aligned headerNew pointer). |
| 175 | HeaderNew* headerNew = (HeaderNew*)data; |
| 176 | data += sizeof(HeaderNew); |
| 177 | if (data >= buffer->data() + buffer->size()) { |
| 178 | return Error("Invalid format"); |
| 179 | } |
| 180 | |
| 181 | EntryNew* entriesNew = (EntryNew*)data; |
| 182 | data += headerNew->libraryCount * sizeof(EntryNew); |
| 183 | if (data >= buffer->data() + buffer->size()) { |
| 184 | return Error("Invalid format"); |
| 185 | } |
| 186 | |
| 187 | // The start of the strings table is at the beginning of |
| 188 | // the new header, per the above format description. |
| 189 | char* strings = (char*)headerNew; |
| 190 | |
| 191 | // Adjust the pointer to add on the additional size of the strings |
| 192 | // contained in the string table. At this point, 'data' should |
| 193 | // point to an address just beyond the end of the file. |
| 194 | data += headerNew->stringsLength; |
| 195 | if ((size_t)(data - buffer->data()) != buffer->size()) { |
| 196 | return Error("Invalid format"); |