@@ -171,82 +171,88 @@ StatusOr<std::pair<std::string, BuildInfo>> ReadGoBuildInfo(ElfReader* elf_reade
171171 PX_ASSIGN_OR_RETURN (uint8_t endianness, binary_decoder.ExtractBEInt <uint8_t >());
172172
173173 BuildInfo build_info;
174+ std::string go_version;
175+ std::string mod_info;
174176 // If the endianness has its second bit set, then the go version immediately follows the 32 bit
175177 // header specified by the varint encoded string data
176178 if ((endianness & 0x2 ) != 0 ) {
177179 // Skip the remaining 16 bytes of buildinfo header
178180 PX_CHECK_OK (binary_decoder.ExtractBufIgnore (16 ));
179181
180182 PX_ASSIGN_OR_RETURN (uint64_t size, binary_decoder.ExtractUVarInt ());
181- PX_ASSIGN_OR_RETURN (std::string_view go_version, binary_decoder.ExtractString (size));
183+ PX_ASSIGN_OR_RETURN (go_version, binary_decoder.ExtractString (size));
182184
183185 PX_ASSIGN_OR_RETURN (uint64_t mod_size, binary_decoder.ExtractUVarInt ());
184- PX_ASSIGN_OR_RETURN (std::string_view mod, binary_decoder.ExtractString (mod_size));
185- if (mod_size >= 33 && mod.at (mod_size - 17 ) == ' \n ' ) {
186- mod.remove_prefix (16 );
187- PX_ASSIGN_OR_RETURN (build_info, ReadModInfo (std::string (mod)));
188- }
189-
190- PX_ASSIGN_OR_RETURN (auto s, ExtractSemVer (std::string (go_version)));
191- return std::make_pair (s, std::move (build_info));
192- }
193-
194- read_ptr_func_t read_ptr;
195- switch (endianness) {
196- case 0x0 : {
197- if (ptr_size == 4 ) {
198- read_ptr = [&](u8string_view str_view) {
199- return utils::LEndianBytesToInt<uint32_t , 4 >(str_view);
200- };
201- } else if (ptr_size == 8 ) {
202- read_ptr = [&](u8string_view str_view) {
203- return utils::LEndianBytesToInt<uint64_t , 8 >(str_view);
204- };
205- } else {
206- return error::NotFound (absl::Substitute (
207- " Binary reported pointer size=$0, refusing to parse non go binary" , ptr_size));
186+ PX_ASSIGN_OR_RETURN (mod_info, binary_decoder.ExtractString (mod_size));
187+ } else {
188+ read_ptr_func_t read_ptr;
189+ switch (endianness) {
190+ case 0x0 : {
191+ if (ptr_size == 4 ) {
192+ read_ptr = [&](u8string_view str_view) {
193+ return utils::LEndianBytesToInt<uint32_t , 4 >(str_view);
194+ };
195+ } else if (ptr_size == 8 ) {
196+ read_ptr = [&](u8string_view str_view) {
197+ return utils::LEndianBytesToInt<uint64_t , 8 >(str_view);
198+ };
199+ } else {
200+ return error::NotFound (absl::Substitute (
201+ " Binary reported pointer size=$0, refusing to parse non go binary" , ptr_size));
202+ }
203+ break ;
208204 }
209- break ;
210- }
211- case 0x1 :
212- if (ptr_size == 4 ) {
213- read_ptr = [&](u8string_view str_view) {
214- return utils::BEndianBytesToInt<uint64_t , 4 >(str_view);
215- };
216- } else if (ptr_size == 8 ) {
217- read_ptr = [&](u8string_view str_view) {
218- return utils::BEndianBytesToInt<uint64_t , 8 >(str_view);
219- };
220- } else {
221- return error::NotFound (absl::Substitute (
222- " Binary reported pointer size=$0, refusing to parse non go binary" , ptr_size));
205+ case 0x1 :
206+ if (ptr_size == 4 ) {
207+ read_ptr = [&](u8string_view str_view) {
208+ return utils::BEndianBytesToInt<uint64_t , 4 >(str_view);
209+ };
210+ } else if (ptr_size == 8 ) {
211+ read_ptr = [&](u8string_view str_view) {
212+ return utils::BEndianBytesToInt<uint64_t , 8 >(str_view);
213+ };
214+ } else {
215+ return error::NotFound (absl::Substitute (
216+ " Binary reported pointer size=$0, refusing to parse non go binary" , ptr_size));
217+ }
218+ break ;
219+ default : {
220+ auto msg =
221+ absl::Substitute (" Invalid endianness=$0, refusing to parse non go binary" , endianness);
222+ DCHECK (false ) << msg;
223+ return error::NotFound (msg);
223224 }
224- break ;
225- default : {
226- auto msg =
227- absl::Substitute (" Invalid endianness=$0, refusing to parse non go binary" , endianness);
228- DCHECK (false ) << msg;
229- return error::NotFound (msg);
230225 }
231- }
232226
233- // Reads the virtual address location of the runtime.buildVersion symbol.
234- PX_ASSIGN_OR_RETURN (auto runtime_version_vaddr,
235- binary_decoder.ExtractString <u8string_view::value_type>(ptr_size));
236- PX_ASSIGN_OR_RETURN (uint64_t ptr_addr,
237- elf_reader->VirtualAddrToBinaryAddr (read_ptr (runtime_version_vaddr)));
227+ // Reads the virtual address location of the runtime.buildVersion symbol.
228+ PX_ASSIGN_OR_RETURN (auto runtime_version_vaddr,
229+ binary_decoder.ExtractString <u8string_view::value_type>(ptr_size));
230+ PX_ASSIGN_OR_RETURN (auto mod_info_vaddr,
231+ binary_decoder.ExtractString <u8string_view::value_type>(ptr_size));
232+ PX_ASSIGN_OR_RETURN (uint64_t ptr_addr,
233+ elf_reader->VirtualAddrToBinaryAddr (read_ptr (runtime_version_vaddr)));
238234
239- PX_ASSIGN_OR_RETURN (auto version , ReadGoString (elf_reader, ptr_size, ptr_addr, read_ptr));
235+ PX_ASSIGN_OR_RETURN (go_version , ReadGoString (elf_reader, ptr_size, ptr_addr, read_ptr));
240236
241- PX_ASSIGN_OR_RETURN (uint64_t mod_ptr_addr, elf_reader->VirtualAddrToBinaryAddr (
242- read_ptr (runtime_version_vaddr) + ptr_size));
243- auto mod_status = ReadGoString (elf_reader, ptr_size, mod_ptr_addr, read_ptr);
244- if (mod_status.ok ()) {
245- std::string mod = mod_status.ValueOrDie ();
246- } else {
247- LOG (WARNING) << " Failed to read mod status" ;
237+ auto mod_ptr_addr_s = elf_reader->VirtualAddrToBinaryAddr (read_ptr (mod_info_vaddr));
238+ if (mod_ptr_addr_s.ok ()) {
239+ PX_ASSIGN_OR_RETURN (mod_info, ReadGoString (elf_reader, ptr_size,
240+ mod_ptr_addr_s.ConsumeValueOrDie (), read_ptr));
241+ }
242+ }
243+
244+ auto mod_size = mod_info.size ();
245+ if (mod_size > 0 ) {
246+ // The module info string is delimited by the sentinel strings cmd/go/internal/modload.infoStart
247+ // and infoEnd. These strings are 16 characters long, so first check that the module info
248+ // contains more than the sentinel strings. This check reflects upstream's implementation
249+ // https://github.com/golang/go/blob/cb7a091d729eab75ccfdaeba5a0605f05addf422/src/debug/buildinfo/buildinfo.go#L214-L215
250+ if (mod_size >= 33 && mod_info.at (mod_size - 17 ) == ' \n ' ) {
251+ mod_info.erase (0 , 16 );
252+ PX_ASSIGN_OR_RETURN (build_info, ReadModInfo (mod_info));
253+ }
248254 }
249- PX_ASSIGN_OR_RETURN (auto s, ExtractSemVer (std::string (version) ));
255+ PX_ASSIGN_OR_RETURN (auto s, ExtractSemVer (go_version ));
250256 return std::make_pair (s, std::move (build_info));
251257}
252258
0 commit comments