()
| 1299 | } |
| 1300 | |
| 1301 | func (ec *elfCode) loadDataSections() error { |
| 1302 | for _, sec := range ec.sections { |
| 1303 | if sec.kind != dataSection { |
| 1304 | continue |
| 1305 | } |
| 1306 | |
| 1307 | // If a section has no references, it will be freed as soon as the |
| 1308 | // Collection closes, so creating and populating it is wasteful. If it has |
| 1309 | // no symbols, it is likely an ephemeral section used during compilation |
| 1310 | // that wasn't sanitized by the bpf linker. (like .rodata.str1.1) |
| 1311 | // |
| 1312 | // No symbols means no VariableSpecs can be generated from it, making it |
| 1313 | // pointless to emit a data section for. |
| 1314 | if sec.references == 0 && len(sec.symbols) == 0 { |
| 1315 | continue |
| 1316 | } |
| 1317 | |
| 1318 | if sec.Size > math.MaxUint32 { |
| 1319 | return fmt.Errorf("data section %s: contents exceed maximum size", sec.Name) |
| 1320 | } |
| 1321 | |
| 1322 | mapSpec := &MapSpec{ |
| 1323 | Name: sanitizeName(sec.Name, -1), |
| 1324 | Type: Array, |
| 1325 | KeySize: 4, |
| 1326 | ValueSize: uint32(sec.Size), |
| 1327 | MaxEntries: 1, |
| 1328 | } |
| 1329 | |
| 1330 | if isConstantDataSection(sec.Name) { |
| 1331 | mapSpec.Flags = sys.BPF_F_RDONLY_PROG |
| 1332 | } |
| 1333 | |
| 1334 | var data []byte |
| 1335 | switch sec.Type { |
| 1336 | // Only open the section if we know there's actual data to be read. |
| 1337 | case elf.SHT_PROGBITS: |
| 1338 | var err error |
| 1339 | data, err = sec.Data() |
| 1340 | if err != nil { |
| 1341 | return fmt.Errorf("data section %s: can't get contents: %w", sec.Name, err) |
| 1342 | } |
| 1343 | |
| 1344 | case elf.SHT_NOBITS: |
| 1345 | // NOBITS sections like .bss contain only zeroes and are not allocated in |
| 1346 | // the ELF. Since data sections are Arrays, the kernel can preallocate |
| 1347 | // them. Don't attempt reading zeroes from the ELF, instead allocate the |
| 1348 | // zeroed memory to support getting and setting VariableSpecs for sections |
| 1349 | // like .bss. |
| 1350 | data = make([]byte, sec.Size) |
| 1351 | |
| 1352 | default: |
| 1353 | return fmt.Errorf("data section %s: unknown section type %s", sec.Name, sec.Type) |
| 1354 | } |
| 1355 | |
| 1356 | mapSpec.Contents = []MapKV{{uint32(0), data}} |
| 1357 | |
| 1358 | for off, sym := range sec.symbols { |
no test coverage detected