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

Correct the handling of p_offset related to the program header in ckb… #49

Merged
merged 3 commits into from
Aug 24, 2023

Conversation

joii2020
Copy link
Contributor

No description provided.

@@ -413,7 +419,7 @@ int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type,
const char *current_str = shrtab + sh->sh_name;
if (strcmp(DYNSTR, current_str) == 0) {
const uint8_t *addr2 =
addr_offset_checked(aligned_addr, aligned_size, sh->sh_offset);
addr_offset_checked(aligned_addr, aligned_size, sh->sh_addr);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add reference or official documents about this changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

References mainly come from these places
In glibc, although sh_offset is used, it is read from the bin file here. In dlopen2, it reads from the memory that has been mapped.
And, it can be known from the official linux description that sh_addr is the address of the virtual memory, and sh_offset is the offset address of the binary file.

glibc code
linux elf in page: 1-11
Wiki linux elf

ckb_dlfcn.h Outdated
@@ -259,7 +259,13 @@ int ckb_dlopen2(const uint8_t *dep_cell_hash, uint8_t hash_type,
if (ph->p_offset < prepad) {
return ERROR_ELF_NOT_ALIGNED;
}
ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset - prepad, ph->p_filesz,
uint64_t offset = ph->p_offset;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I wasn't following the logic here.

The original code does have a bug indeed, I also noticed it when I was tweaking other code. I believe the following code can already work:

ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset - prepad, ph->p_filesz + prepad, index, CKB_SOURCE_CELL_DEP);

I wonder if there's anything else needed.

ckb_dlfcn.h Outdated
ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset - prepad, ph->p_filesz,
uint64_t offset = ph->p_offset;
uint64_t read_size = ph->p_filesz;
if (offset % RISCV_PGSIZE != 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Do we really need to align file offset? I personally wasn't sure if there is a need for that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Actually, this change is identical to :

ret = _ckb_load_cell_code(addr2, memsz, ph->p_offset - prepad, ph->p_filesz + prepad, index, CKB_SOURCE_CELL_DEP);

The same padding is calculated, twice.

Copy link
Collaborator

Choose a reason for hiding this comment

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

In that sense I don't think we need this bulk of changes, we have prepad above, which is also used in a condition, we can simply make the one line change, there is no need to calculate the padding again here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The prepad is calculated from p_vaddr. As we know, p_vaddr and p_offset should satisfy:
p_vaddr - p_offset % align == 0, which align can be 4096, or 2048, ... even 1, depending or compiler or linker script.
When align is not 4096, these paddings are not same.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We could debate the formula used to calculate padding, but for one library, there should be only one padding used, so I would suggest either use prepad and delete the rest, or keep current implementation, and delete parts related to prepad. Current code, IMHO, is slightly messy.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Correct: When padding are not same, we should take original prepad: p_vaddr % RISCV_PGSIZE.

@xxuejie
Copy link
Collaborator

xxuejie commented Aug 22, 2023

If you want to calculate padding in the correct way, you should remove code related to prepad

@XuJiandong XuJiandong merged commit 648d20d into nervosnetwork:master Aug 24, 2023
XuJiandong added a commit to XuJiandong/ckb-std that referenced this pull request Aug 24, 2023
XuJiandong added a commit to nervosnetwork/ckb-std that referenced this pull request Aug 24, 2023
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.

None yet

3 participants