Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for 64bit immediate with type 2 (load map value address). #119

Closed
wants to merge 1 commit into from

Conversation

Alan-Jowett
Copy link
Owner

@Alan-Jowett Alan-Jowett commented Jan 7, 2025

Add support to the verifier to handle 64bit immediate loads with source == 2, which is defined as:

5.4.  64-bit immediate instructions

   Instructions with the IMM 'mode' modifier use the wide instruction
   encoding defined in Instruction encoding (Section 3), and use the
   'src_reg' field of the basic instruction to hold an opcode subtype.

   The following table defines a set of {IMM, DW, LD} instructions with
   opcode subtypes in the 'src_reg' field, using new terms such as "map"
   defined further below:

    +=========+================================+==========+==========+
    | src_reg | pseudocode                     | imm type | dst type |
    +=========+================================+==========+==========+
    | 0x0     | dst = (next_imm << 32) | imm   | integer  | integer  |
    +---------+--------------------------------+----------+----------+
    | 0x1     | dst = map_by_fd(imm)           | map fd   | map      |
    +---------+--------------------------------+----------+----------+
    | 0x2     | dst = map_val(map_by_fd(imm))  | map fd   | data     |
    |         | + next_imm                     |          | address  |
    +---------+--------------------------------+----------+----------+
    | 0x3     | dst = var_addr(imm)            | variable | data     |
    |         |                                | id       | address  |
    +---------+--------------------------------+----------+----------+
    | 0x4     | dst = code_addr(imm)           | integer  | code     |
    |         |                                |          | address  |
    +---------+--------------------------------+----------+----------+
    | 0x5     | dst = map_by_idx(imm)          | map      | map      |
    |         |                                | index    |          |
    +---------+--------------------------------+----------+----------+
    | 0x6     | dst = map_val(map_by_idx(imm)) | map      | data     |
    |         | + next_imm                     | index    | address  |
    +---------+--------------------------------+----------+----------+

                 Table 12: 64-bit immediate instructions

Generated PR description
This pull request introduces several significant changes to the codebase, focusing on the addition of support for a new LoadMapAddress instruction, enhancements to ELF file handling, and various updates to the instruction set and related components. Below is a summary of the most important changes:

Support for LoadMapAddress Instruction:

  • Added a new LoadMapAddress struct to the instruction set (src/asm_syntax.hpp). [1] [2]
  • Updated the instype function to handle the LoadMapAddress instruction (src/asm_cfg.cpp).
  • Implemented marshalling and unmarshalling for LoadMapAddress (src/asm_marshal.cpp, src/asm_unmarshal.cpp). [1] [2] [3]
  • Enhanced the CommandPrinterVisitor to support LoadMapAddress (src/asm_ostream.cpp). [1] [2]

ELF File Handling Enhancements:

  • Introduced handling for global variables in ELF sections, including .data, .bss, and .rodata sections (src/asm_files.cpp). [1] [2] [3] [4] [5] [6]

Transformer and Assertion Updates:

  • Updated the ebpf_transformer class to handle LoadMapAddress instructions (src/crab/ebpf_transformer.cpp). [1] [2] [3]
  • Added assertion handling for LoadMapAddress in the AssertExtractor class (src/assertions.cpp).

Miscellaneous Changes:

  • Updated the submodule commit for external/libbtf to a new commit (external/libbtf).
  • Included the <assert.h> header in src/asm_files.cpp for assertions (src/asm_files.cpp).

Summary by CodeRabbit

  • New Features

    • Added support for loading map addresses in eBPF instruction set
    • Enhanced instruction handling for map-related operations
  • Bug Fixes

    • Improved error handling and validation for map address instructions
  • Refactor

    • Updated instruction processing across multiple components to support new map address functionality

Copy link

coderabbitai bot commented Jan 7, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

This pull request introduces a new instruction type LoadMapAddress to the eBPF instruction set. The changes span multiple source files to support this new instruction, including modifications to parsing, marshaling, unmarshaling, and transformation processes. The implementation adds capabilities for handling map address loading, with updates to various components of the compilation and processing pipeline to recognize and process this new instruction type.

Changes

File Change Summary
external/libbtf Subproject commit updated from 3c0cbd6 to 6aba160
src/asm_cfg.cpp Added conditional branch in instype to handle LoadMapAddress instruction
src/asm_files.cpp Added relocate_global_variable function and updated read_elf to handle global variable sections
src/asm_marshal.cpp Added operator() for LoadMapAddress in MarshalVisitor with error handling
src/asm_ostream.cpp Added operator() to CommandPrinterVisitor for formatting LoadMapAddress output
src/asm_syntax.hpp Introduced new LoadMapAddress structure and updated Instruction variant
src/asm_unmarshal.cpp Modified makeLddw to support new map address loading logic
src/assertions.cpp Added operator() for LoadMapAddress in AssertExtractor
src/crab/ebpf_transformer.cpp Added do_load_map_address method and operator for LoadMapAddress

Sequence Diagram

sequenceDiagram
    participant Parser as Instruction Parser
    participant Unmarshaller as Unmarshaller
    participant Transformer as eBPF Transformer
    participant Marshaller as Marshaller

    Parser->>Unmarshaller: Parse instruction
    Unmarshaller-->>Parser: Create LoadMapAddress instruction
    Parser->>Transformer: Transform instruction
    Transformer-->>Parser: Process map address loading
    Parser->>Marshaller: Marshal instruction
    Marshaller-->>Parser: Prepare instruction for execution
Loading

Poem

🐰 A Rabbit's Ode to Map Address Loading

In bytecode's realm, a new path unfurls,
LoadMapAddress, where magic twirls!
Two registers dance, a map's embrace,
With offset and fd, we'll find our place 🗺️
A leap of code, both nimble and bright! 🚀


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@Alan-Jowett
Copy link
Owner Author

@coderabbitai review

Copy link

coderabbitai bot commented Jan 7, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
src/asm_files.cpp (1)

401-402: Remove unused variable 'map_descriptors_offsets'

The variable map_descriptors_offsets declared at line 401 is unused, leading to a compiler warning and potential confusion. Consider removing it to clean up the code.

Apply this diff to remove the unused variable:

-    auto& map_descriptors_offsets = std::get<1>(map_record_size_or_map_offsets);
🧰 Tools
🪛 GitHub Actions: CPP Code Coverage

[warning] 401-401: Unused variable 'map_descriptors_offsets'

src/asm_marshal.cpp (1)

311-313: Synchronize size function with marshaling logic

Since the marshaling logic for LoadMapAddress should produce two instructions, the size function correctly returns 2. Ensure that this size corresponds to the implemented marshaling logic.

After implementing the marshaling logic, confirm that the size function accurately reflects the number of instructions generated for LoadMapAddress.

src/asm_unmarshal.cpp (1)

Line range hint 432-452: LGTM! Consider adding a comment for the magic number.

The implementation correctly handles the LoadMapAddress instruction type, maintaining consistency with existing error handling and validation.

Consider adding a comment explaining the magic number 2, similar to the comment for src == 1:

 if (inst.src == 2) {
+    // magic number, meaning we're loading a map value address
+    // (for details, look for BPF_PSEUDO_MAP_VALUE in the kernel)
     return LoadMapAddress{.dst = Reg{inst.dst}, .mapfd = inst.imm, .offset = next_imm};
 }
src/crab/ebpf_transformer.cpp (1)

1844-1854: Add input validation and documentation.

While the implementation is functionally correct, consider these improvements:

  1. Add input validation for the offset parameter to ensure it's within bounds of the map's value size.
  2. Add documentation explaining the method's purpose and behavior.
  3. Add error handling for map descriptor lookup failures.

Here's a suggested implementation with the improvements:

+/**
+ * Loads a map's address with the specified offset into a register.
+ * 
+ * @param dst_reg The destination register
+ * @param mapfd The map file descriptor
+ * @param offset The offset within the map's value region
+ * @throws std::out_of_range if the map descriptor lookup fails
+ */
 void ebpf_transformer::do_load_map_address(const Reg& dst_reg, const int mapfd, int32_t offset) {
     const EbpfMapDescriptor& desc = thread_local_program_info->platform->get_map_descriptor(mapfd);
     const EbpfMapType& type = thread_local_program_info->platform->get_map_type(desc.type);
 
+    // Validate offset is within bounds
+    if (offset < 0 || offset >= desc.value_size) {
+        throw std::out_of_range("Map address offset out of bounds");
+    }
+
     // Set the shared region size and offset for the map.
     type_inv.assign_type(m_inv, dst_reg, T_SHARED);
     const reg_pack_t& dst = reg_pack(dst_reg);
     m_inv.assign(dst.shared_offset, offset);
     m_inv.assign(dst.shared_region_size, desc.value_size);
     assign_valid_ptr(dst_reg, false);
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46344ae and b90d048.

📒 Files selected for processing (9)
  • external/libbtf (1 hunks)
  • src/asm_cfg.cpp (1 hunks)
  • src/asm_files.cpp (7 hunks)
  • src/asm_marshal.cpp (2 hunks)
  • src/asm_ostream.cpp (2 hunks)
  • src/asm_syntax.hpp (2 hunks)
  • src/asm_unmarshal.cpp (2 hunks)
  • src/assertions.cpp (1 hunks)
  • src/crab/ebpf_transformer.cpp (3 hunks)
✅ Files skipped from review due to trivial changes (1)
  • external/libbtf
🧰 Additional context used
🪛 GitHub Actions: CPP Code Coverage
src/asm_files.cpp

[warning] 287-287: Comparison of integer expressions of different signedness: 'int' and 'std::map<int, btf_line_info_t>::size_type'


[warning] 401-401: Unused variable 'map_descriptors_offsets'

🔇 Additional comments (9)
src/asm_files.cpp (2)

Line range hint 287-287: Address signedness comparison warning

A compiler warning indicates a comparison between an int and a size_t type at line 287. This can lead to unexpected behavior due to signedness mismatch. Ensure that both operands are of the same type by casting or changing variable types as necessary.

Since the specific code is not shown, please review line 287 to correct the signed/unsigned comparison. If some_int_variable is of type int, consider casting it to size_t or changing its type.


499-504: ⚠️ Potential issue

Potential out-of-bounds access in inst_next

In the relocate_global_variable call, inst_next may reference an instruction beyond the end of the program if not properly checked. Ensure that inst_next is within the bounds of prog.prog to prevent undefined behavior.

Please verify that inst_next is valid before accessing it. You can modify the code to include a boundary check:

 ebpf_inst& inst = prog.prog[offset / sizeof(ebpf_inst)];
-ebpf_inst& inst_next = offset / sizeof(ebpf_inst) + 1 < prog.prog.size()
-                           ? prog.prog[offset / sizeof(ebpf_inst) + 1]
-                           : inst;
+size_t inst_index = offset / sizeof(ebpf_inst);
+ebpf_inst& inst_next = inst_index + 1 < prog.prog.size()
+                           ? prog.prog[inst_index + 1]
+                           : inst;
src/asm_syntax.hpp (1)

96-104: 🛠️ Refactor suggestion

Ensure consistent handling of LoadMapAddress in visitors

The new LoadMapAddress instruction has been added to the Instruction variant. Please verify that all visitor patterns and handlers throughout the codebase are updated to accommodate this new instruction to prevent unhandled cases.

Ensure that any code relying on pattern matching over Instruction handles LoadMapAddress appropriately. This includes updating visitors, switch statements, and other pattern matches.

src/assertions.cpp (1)

48-48: LGTM!

The implementation is consistent with other map-related operations in the class, and correctly returns an empty vector of assertions for the LoadMapAddress instruction.

src/asm_cfg.cpp (1)

402-403: LGTM!

The classification of LoadMapAddress as an "assign" instruction type is consistent with similar map-related operations like LoadMapFd.

src/asm_ostream.cpp (2)

362-363: LGTM!

The formatting of LoadMapAddress instructions is clear and consistent with the codebase's style.


556-558: LGTM!

The size of 2 for LoadMapAddress instructions is consistent with similar instructions like LoadMapFd.

src/crab/ebpf_transformer.cpp (2)

47-47: LGTM! Method declaration follows class conventions.

The declaration of operator()(const LoadMapAddress&) is well-placed among other instruction handlers and follows the established pattern of the class.


1856-1857: LGTM! Simple delegation to helper method.

The operator implementation correctly delegates to the helper method, maintaining a clean separation of concerns.

src/asm_marshal.cpp Outdated Show resolved Hide resolved
@Alan-Jowett Alan-Jowett changed the title First draft Add support for 64bit immediate with type 2 (load map value address). Jan 7, 2025
src/asm_files.cpp Outdated Show resolved Hide resolved
src/asm_unmarshal.cpp Outdated Show resolved Hide resolved
src/asm_unmarshal.cpp Outdated Show resolved Hide resolved
@Alan-Jowett Alan-Jowett force-pushed the load_map_address branch 4 times, most recently from f863c07 to 831cc0a Compare January 13, 2025 18:36
From the ISA RFC:
5.4.  64-bit immediate instructions

   Instructions with the IMM 'mode' modifier use the wide instruction
   encoding defined in Instruction encoding (Section 3), and use the
   'src_reg' field of the basic instruction to hold an opcode subtype.

   The following table defines a set of {IMM, DW, LD} instructions with
   opcode subtypes in the 'src_reg' field, using new terms such as "map"
   defined further below:

    +=========+================================+==========+==========+
    | src_reg | pseudocode                     | imm type | dst type |
    +=========+================================+==========+==========+
    | 0x0     | dst = (next_imm << 32) | imm   | integer  | integer  |
    +---------+--------------------------------+----------+----------+
    | 0x1     | dst = map_by_fd(imm)           | map fd   | map      |
    +---------+--------------------------------+----------+----------+
    | 0x2     | dst = map_val(map_by_fd(imm))  | map fd   | data     |
    |         | + next_imm                     |          | address  |
    +---------+--------------------------------+----------+----------+
    | 0x3     | dst = var_addr(imm)            | variable | data     |
    |         |                                | id       | address  |
    +---------+--------------------------------+----------+----------+
    | 0x4     | dst = code_addr(imm)           | integer  | code     |
    |         |                                |          | address  |
    +---------+--------------------------------+----------+----------+
    | 0x5     | dst = map_by_idx(imm)          | map      | map      |
    |         |                                | index    |          |
    +---------+--------------------------------+----------+----------+
    | 0x6     | dst = map_val(map_by_idx(imm)) | map      | data     |
    |         | + next_imm                     | index    | address  |
    +---------+--------------------------------+----------+----------+

                 Table 12: 64-bit immediate instructions

Signed-off-by: Alan Jowett <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants