Rocksolid Light

Welcome to novaBBS (click a section below)

mail  files  register  newsreader  groups  login

Message-ID:  

If an experiment works, something has gone wrong.


devel / comp.lang.c / Pointer offset/arithmetic into a void * buffer

SubjectAuthor
* Pointer offset/arithmetic into a void * bufferJames Harris
+* Re: Pointer offset/arithmetic into a void * bufferBart
|`* Re: Pointer offset/arithmetic into a void * bufferJames Harris
| `* Re: Pointer offset/arithmetic into a void * bufferBen Bacarisse
|  `* Re: Pointer offset/arithmetic into a void * bufferJames Harris
|   `* Re: Pointer offset/arithmetic into a void * bufferBen Bacarisse
|    `- Re: Pointer offset/arithmetic into a void * bufferJames Harris
`* Re: Pointer offset/arithmetic into a void * bufferKeith Thompson
 `- Re: Pointer offset/arithmetic into a void * bufferScott Lurndal

1
Pointer offset/arithmetic into a void * buffer

<s8ik8f$nv$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16656&group=comp.lang.c++#16656

  copy link   Newsgroups: comp.lang.c
 by: James Harris - Tue, 25 May 2021 10:41 UTC

Say mmap has returned a void * pointer to an in-memory image of a file.

The file header, because it's at offset 0, can naturally be accessed by
assigning the value returned into a pointer of the right type.

But the header says that there's a 'section structure' 712 bytes from
the start of the file and I am not sure what's the best way to set up a
pointer to that structure.

I know I can cast the original pointer to a char *, add 712 to it (or
take the address of the byte at offset 712), and cast it to a pointer of
the right type for the section structure; and that would work for the
architecture I need it for.

But to do this 'properly' is there a better or more standard or more
portable way to set the pointer to the section structure that doesn't
require the casts?

--
James Harris

Re: Pointer offset/arithmetic into a void * buffer

<3I4rI.610898$hcZe.171575@fx46.ams4>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16658&group=comp.lang.c++#16658

  copy link   Newsgroups: comp.lang.c
 by: Bart - Tue, 25 May 2021 10:54 UTC

On 25/05/2021 11:41, James Harris wrote:
> Say mmap has returned a void * pointer to an in-memory image of a file.
>
> The file header, because it's at offset 0, can naturally be accessed by
> assigning the value returned into a pointer of the right type.
>
> But the header says that there's a 'section structure' 712 bytes from
> the start of the file and I am not sure what's the best way to set up a
> pointer to that structure.
>
> I know I can cast the original pointer to a char *, add 712 to it (or
> take the address of the byte at offset 712), and cast it to a pointer of
> the right type for the section structure; and that would work for the
> architecture I need it for.
>
> But to do this 'properly' is there a better or more standard or more
> portable way to set the pointer to the section structure that doesn't
> require the casts?
>
>
>

Not sure what the problem is with the casts; it might be the only with a
file layout that is not determinable at compile-time.

But perhaps something like this:

#include <stdio.h>

typedef struct{
char stuff[100];
} Section;

typedef struct {
char fileheader[712];
Section sectinfo;
char rest[];
} Image;

int main(void) {
Image* p;
Section* q = &(p->sectinfo);
}

p points to the whole file image. q points to the section structure. But
if you were to look at the generated code, it just ends up adding 712 to
p to get q! Exactly what you were trying to avoid.

So I wouldn't worry about it.

Re: Pointer offset/arithmetic into a void * buffer

<s8im57$gvc$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16659&group=comp.lang.c++#16659

  copy link   Newsgroups: comp.lang.c
 by: James Harris - Tue, 25 May 2021 11:13 UTC

On 25/05/2021 11:54, Bart wrote:
> On 25/05/2021 11:41, James Harris wrote:
>> Say mmap has returned a void * pointer to an in-memory image of a file.
>>
>> The file header, because it's at offset 0, can naturally be accessed
>> by assigning the value returned into a pointer of the right type.
>>
>> But the header says that there's a 'section structure' 712 bytes from
>> the start of the file and I am not sure what's the best way to set up
>> a pointer to that structure.
>>
>> I know I can cast the original pointer to a char *, add 712 to it (or
>> take the address of the byte at offset 712), and cast it to a pointer
>> of the right type for the section structure; and that would work for
>> the architecture I need it for.
>>
>> But to do this 'properly' is there a better or more standard or more
>> portable way to set the pointer to the section structure that doesn't
>> require the casts?
>>
>>
>>
>
>
> Not sure what the problem is with the casts; it might be the only with a
> file layout that is not determinable at compile-time.

Casts prevent type checking and are too-easily used to mask a type
mismatch but I agree that there may be no alternative in some cases.

>
> But perhaps something like this:
>
>     #include <stdio.h>
>
>     typedef struct{
>         char stuff[100];
>     } Section;
>
>     typedef struct {
>         char fileheader[712];
>         Section sectinfo;
>         char rest[];
>     } Image;

The offset of 712 is just an example. It is what I read from the header
of one particular file. It is not a constant. Different files will have
different offsets.

>
>
>     int main(void) {
>         Image* p;
>         Section* q = &(p->sectinfo);
>     }
>
> p points to the whole file image. q points to the section structure. But
> if you were to look at the generated code, it just ends up adding 712 to
> p to get q! Exactly what you were trying to avoid.
>
> So I wouldn't worry about it.

:-)

--
James Harris

Re: Pointer offset/arithmetic into a void * buffer

<87y2c3kq46.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16660&group=comp.lang.c++#16660

  copy link   Newsgroups: comp.lang.c
 by: Ben Bacarisse - Tue, 25 May 2021 11:30 UTC

James Harris <james.harris.1@gmail.com> writes:

> On 25/05/2021 11:54, Bart wrote:
>> On 25/05/2021 11:41, James Harris wrote:
>>> Say mmap has returned a void * pointer to an in-memory image of a file.
>>>
>>> The file header, because it's at offset 0, can naturally be accessed
>>> by assigning the value returned into a pointer of the right type.
>>>
>>> But the header says that there's a 'section structure' 712 bytes
>>> from the start of the file and I am not sure what's the best way to
>>> set up a pointer to that structure.
>>>
>>> I know I can cast the original pointer to a char *, add 712 to it
>>> (or take the address of the byte at offset 712), and cast it to a
>>> pointer of the right type for the section structure; and that would
>>> work for the architecture I need it for.
>>>
>>> But to do this 'properly' is there a better or more standard or more
>>> portable way to set the pointer to the section structure that
>>> doesn't require the casts?
>>
>> Not sure what the problem is with the casts; it might be the only
>> with a file layout that is not determinable at compile-time.
>
> Casts prevent type checking and are too-easily used to mask a type
> mismatch but I agree that there may be no alternative in some cases.

Technically, a cast is an operator and you can do this without casts.
It's C's permitted type conversions that you are objecting to because
they can hide type errors.

If you can describe the file contents as a C struct, then you can get
the pointer without any conversion, but...

<cut>
> The offset of 712 is just an example. It is what I read from the
> header of one particular file. It is not a constant. Different files
> will have different offsets.

.... it seems like you won't be able to do that.

Is part of the problem that you'd like C to help with calculating the
offset? If so, you can use all sort of tricks to make the code more
portable, including pretending to have a pointer to a variably modified
array type. You'll still be using casts (or implicit conversions) but
the code might be much more portable.

--
Ben.

Re: Pointer offset/arithmetic into a void * buffer

<s8iv9u$mka$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16662&group=comp.lang.c++#16662

  copy link   Newsgroups: comp.lang.c
 by: James Harris - Tue, 25 May 2021 13:49 UTC

On 25/05/2021 12:30, Ben Bacarisse wrote:
> James Harris <james.harris.1@gmail.com> writes:
>
>> On 25/05/2021 11:54, Bart wrote:
>>> On 25/05/2021 11:41, James Harris wrote:

....

>>>> But to do this 'properly' is there a better or more standard or more
>>>> portable way to set the pointer to the section structure that
>>>> doesn't require the casts?

....

> Is part of the problem that you'd like C to help with calculating the
> offset? If so, you can use all sort of tricks to make the code more
> portable, including pretending to have a pointer to a variably modified
> array type. You'll still be using casts (or implicit conversions) but
> the code might be much more portable.

No, no calculation is needed. Effectively, the file is specified to be,
as you may expect, an array of 8-bit bytes and the offset - in terms of
such bytes - is given by a value in the file header.

You mentioned making the code more portable or using implicit
conversions - which sounds interesting. The following code is an extract
of the relevant lines. Would you recommend any changes to them?

void elf_report(FILE *f)
{ uint8_t *bp; /* Byte pointer into the file */
void *fbuf; /* Pointer to start of file buffer */
Elf32_Ehdr *eh; /* Pointer to Elf header */
Elf32_Shdr *sh; /* Pointer to section header array */

fbuf = mmap(NULL, flen, PROT_READ, MAP_SHARED, fileno(f), 0);
bp = fbuf;
eh = fbuf;

sh = (Elf32_Shdr *) &bp[eh->e_shoff];

--
James Harris

Re: Pointer offset/arithmetic into a void * buffer

<871r9u5136.fsf@nosuchdomain.example.com>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16665&group=comp.lang.c++#16665

  copy link   Newsgroups: comp.lang.c
 by: Keith Thompson - Tue, 25 May 2021 14:39 UTC

James Harris <james.harris.1@gmail.com> writes:
> Say mmap has returned a void * pointer to an in-memory image of a file.
>
> The file header, because it's at offset 0, can naturally be accessed
> by assigning the value returned into a pointer of the right type.
>
> But the header says that there's a 'section structure' 712 bytes from
> the start of the file and I am not sure what's the best way to set up
> a pointer to that structure.
>
> I know I can cast the original pointer to a char *, add 712 to it (or
> take the address of the byte at offset 712), and cast it to a pointer
> of the right type for the section structure; and that would work for
> the architecture I need it for.
>
> But to do this 'properly' is there a better or more standard or more
> portable way to set the pointer to the section structure that doesn't
> require the casts?

Do you have a C type that corresponds to the first 712 bytes of the
file? Say something like struct header { ... } such that sizeof (struct
header) is guaranteed to be 712? If so, then you can use pointer
arithmetic using that type rather than char.

void *beginning = mmap(...);
void *after_header = (void*)((struct header*)beginning + 1);

You'll probably also want some kind of assertion that the header struct
has the right size.

I'm not entirely sure this is an improvement over char* arithmetic, but
it's something to consider.

--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */

Re: Pointer offset/arithmetic into a void * buffer

<87sg2alvbm.fsf@bsb.me.uk>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16666&group=comp.lang.c++#16666

  copy link   Newsgroups: comp.lang.c
 by: Ben Bacarisse - Tue, 25 May 2021 14:52 UTC

James Harris <james.harris.1@gmail.com> writes:

> On 25/05/2021 12:30, Ben Bacarisse wrote:
>> James Harris <james.harris.1@gmail.com> writes:
>>
>>> On 25/05/2021 11:54, Bart wrote:
>>>> On 25/05/2021 11:41, James Harris wrote:
>
> ...
>
>>>>> But to do this 'properly' is there a better or more standard or more
>>>>> portable way to set the pointer to the section structure that
>>>>> doesn't require the casts?
>
> ...
>
>> Is part of the problem that you'd like C to help with calculating the
>> offset? If so, you can use all sort of tricks to make the code more
>> portable, including pretending to have a pointer to a variably modified
>> array type. You'll still be using casts (or implicit conversions) but
>> the code might be much more portable.
>
> No, no calculation is needed. Effectively, the file is specified to
> be, as you may expect, an array of 8-bit bytes and the offset - in
> terms of such bytes - is given by a value in the file header.
>
> You mentioned making the code more portable or using implicit
> conversions - which sounds interesting.

Implicit pointer conversions sometimes let you avoid a cast as you can
see from the code snippet. It uses them twice. I don't think you can
get any more simplification.

> void elf_report(FILE *f)
> {
> uint8_t *bp; /* Byte pointer into the file */
> void *fbuf; /* Pointer to start of file buffer */
> Elf32_Ehdr *eh; /* Pointer to Elf header */
> Elf32_Shdr *sh; /* Pointer to section header array */
>
> fbuf = mmap(NULL, flen, PROT_READ, MAP_SHARED, fileno(f), 0);
> bp = fbuf;
> eh = fbuf;
>
> sh = (Elf32_Shdr *) &bp[eh->e_shoff];

The only portability issue is that e_shoff might be multi-byte and have
endian issues.

For reasons I have not been able to pin down very well, I prefer to
avoid repeating types all the time, so I would add an implicit
conversion here, but not one that sames a cast:

sh = (void *)&bp[eh->e_shoff];

I am not recommending that.

--
Ben.

Re: Pointer offset/arithmetic into a void * buffer

<w79rI.154798$Y87.68521@fx08.iad>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16668&group=comp.lang.c++#16668

  copy link   Newsgroups: comp.lang.c
 by: Scott Lurndal - Tue, 25 May 2021 15:57 UTC

Keith Thompson <Keith.S.Thompson+u@gmail.com> writes:
>James Harris <james.harris.1@gmail.com> writes:
>> Say mmap has returned a void * pointer to an in-memory image of a file.
>>
>> The file header, because it's at offset 0, can naturally be accessed
>> by assigning the value returned into a pointer of the right type.
>>
>> But the header says that there's a 'section structure' 712 bytes from
>> the start of the file and I am not sure what's the best way to set up
>> a pointer to that structure.
>>
>> I know I can cast the original pointer to a char *, add 712 to it (or
>> take the address of the byte at offset 712), and cast it to a pointer
>> of the right type for the section structure; and that would work for
>> the architecture I need it for.
>>
>> But to do this 'properly' is there a better or more standard or more
>> portable way to set the pointer to the section structure that doesn't
>> require the casts?
>
>Do you have a C type that corresponds to the first 712 bytes of the
>file? Say something like struct header { ... } such that sizeof (struct
>header) is guaranteed to be 712? If so, then you can use pointer
>arithmetic using that type rather than char.
>
> void *beginning = mmap(...);
> void *after_header = (void*)((struct header*)beginning + 1);
>
>You'll probably also want some kind of assertion that the header struct
>has the right size.
>
>I'm not entirely sure this is an improvement over char* arithmetic, but
>it's something to consider.

Usually there is a library to handle this, for example libelf:

if (elf_version(EV_CURRENT) == EV_NONE) {
lp->log("ELF library initialization failure for '%s': %s\n",
filename, elf_errmsg(-1));
goto leave;
}

elf = elf_begin(fd, ELF_C_READ, NULL);
if (elf == NULL) {
lp->log("ELF Codefile access failure for '%s': %s\n",
filename, elf_errmsg(-1));
goto leave;
}

if (elf_kind(elf) != ELF_K_ELF) {
lp->log("File '%s' is not an ELF file\n", filename);
goto leave;
}

ident = elf_getident(elf, NULL);

if (ident[EI_CLASS] == ELFCLASS32) {
rval = load_elf32(fd, elf, filename, options, lp, base_address);
goto leave;
}

if (ident[EI_CLASS] != ELFCLASS64) {
lp->log("File '%s' is not a 64-bit ELF codefile\n", filename);
goto leave;
}

hdr = elf64_getehdr(elf);
if (hdr->e_type != ET_EXEC) {
lp->log("File '%s' is not an executable\n", filename);
goto leave;
}

Elf64_Phdr *phdr = NULL;

phdr = elf64_getphdr(elf);
if (phdr == NULL) {
lp->log("The ELF file '%s' seems broken: "
"Cannot retrieve program headers: %s\n",
filename, elf_errmsg(-1));
goto leave;
}

for(size_t ph = 0; ph < hdr->e_phnum; ph++, phdr++) {
if (phdr->p_type != PT_LOAD) continue; // ignore debug info, etc...
....

Re: Pointer offset/arithmetic into a void * buffer

<s9iqin$9h3$1@dont-email.me>

  copy mid

https://www.novabbs.com/devel/article-flat.php?id=16867&group=comp.lang.c++#16867

  copy link   Newsgroups: comp.lang.c
 by: James Harris - Sun, 6 Jun 2021 15:45 UTC

On 25/05/2021 15:52, Ben Bacarisse wrote:
> James Harris <james.harris.1@gmail.com> writes:
>
>> On 25/05/2021 12:30, Ben Bacarisse wrote:
>>> James Harris <james.harris.1@gmail.com> writes:
>>>
>>>> On 25/05/2021 11:54, Bart wrote:
>>>>> On 25/05/2021 11:41, James Harris wrote:
>>
>> ...
>>
>>>>>> But to do this 'properly' is there a better or more standard or more
>>>>>> portable way to set the pointer to the section structure that
>>>>>> doesn't require the casts?

....

> Implicit pointer conversions sometimes let you avoid a cast as you can
> see from the code snippet. It uses them twice. I don't think you can
> get any more simplification.

That's reassuring, thanks.

>
>> void elf_report(FILE *f)
>> {
>> uint8_t *bp; /* Byte pointer into the file */
>> void *fbuf; /* Pointer to start of file buffer */
>> Elf32_Ehdr *eh; /* Pointer to Elf header */
>> Elf32_Shdr *sh; /* Pointer to section header array */
>>
>> fbuf = mmap(NULL, flen, PROT_READ, MAP_SHARED, fileno(f), 0);
>> bp = fbuf;
>> eh = fbuf;
>>
>> sh = (Elf32_Shdr *) &bp[eh->e_shoff];
>
> The only portability issue is that e_shoff might be multi-byte and have
> endian issues.

Understood; and covered: my code checks the file's declared endianness.

>
> For reasons I have not been able to pin down very well, I prefer to
> avoid repeating types all the time, so I would add an implicit
> conversion here, but not one that sames a cast:
>
> sh = (void *)&bp[eh->e_shoff];
>
> I am not recommending that.

I've been thinking about that - and ended up querying it in a new thread.

--
James Harris

1
server_pubkey.txt

rocksolid light 0.9.81
clearnet tor