Execv Working Without Padding Strings

When we were completing the bigexec test we were failing on the 10th test as a result of one of the kasserts failing. Before we actually realized the correct way to solve it we thought that reducing how big of a stack we hand-off would solve the issue.

@noahpocz had the idea, since we had to be 4 byte aligned, to reduce the string padding down to only one null terminator and simply guarantee our end offset is divisible by 4.

Once the new method was implemented none of the previous functionality actually broke. We still did not pass bigexec but argument passing did not break at all.

Is this actually a valid way of passing arguments and if so I was just curious why padding the strings is the suggested method of going about things?

The extra padding is to align the pointers to the strings, not the strings themselves. All strings have to be NULL-terminated with a single NULL byte. What goes in between the NULL terminator and the start of the next string doesn’t really matter.

Does that make sense?

1 Like

What we did was, when we constructed the bytes to load into the stack, we just loaded in the strings one after another without regard to 4 byte alignment, and kept track of the byte offset of each string from the beginning of the array. Then, when we loaded the bytes onto the user stack, we added the stack pointer to each byte offset to yield the argument pointer to the exact memory address on the stack where each string was stored. So, the argument pointers were not four byte aligned, but it still worked. This saves more memory on the user stack because we’re not including “unnecessary” null terminators. Is there any reason this shouldn’t be done?

1 Like

Does this actually work? Can you confirm that it works for strings of arbitrary length? Maybe OS/161 pointers don’t really have to be word aligned…?

We’re going to reimplement it in a little bit and do further testing but from what we tested it did. We’ll let you know soon.

We just submitted our implementation that ignores 4 byte alignment and received full credit for the assignment.

The implementation is branched in our repo if you would like to take a look at it.

Isn’t word aligning pointers only useful for pointer arithmetic? Rather than having to typecast to char * you can just increment the pointer. But if you don’t mind typecasting why would there be an issue?

I just wrote some test user code and iterating over the args using pointer incrementing rather than argc works.

Is this what you meant or is it something else that should be tested?

No. I that that this was supposed to be an alignment problem.

On some architectures loads and stores have alignment requirements. For example, I can only load and store memory address on 2 or 4 byte boundaries.

1 Like

From the oracle (i.e., David Holland):

Like most non-x86 architectures it requires n-byte objects to be
aligned on an n-byte boundary. Since strings are made up of 1-byte
objects, they have to be aligned to a 1-byte boundary.

Many ABI specifications call for e.g. string constants to be
word-aligned regardless, because then copy operations can go
word-at-a-time. (Or at least, some copy operations. I fail to see an
obvious way to implement word-at-a-time strcpy that’s actually any
better than reading successive bytes out of the L1 cache. But memcpy
is definitely faster word-at-a-time, especially in sys161.)

This point is somewhat subtle and so it gets repeated incorrectly all
over the place, and massive amounts of confusion then follow.

(people here have been confused about it too)