<geist>
yah that's what i'm wondering, why i haven't heard much about valgrind lately. maybe it's because it's intrinsically slower and compiler based sanitizers are maybe not as good but easier to use
<heat>
and way faster
<heat>
(right?)
<klange>
I like callgrind over gcc's integrated perf stuff. I can never figure out how the hell to actually examine the gcc perf output.
<klange>
And then 'perf' is just... a nightmare ime.
freakazoid333 has quit [Ping timeout: 244 seconds]
<klange>
heat: confirmed fix works, now I can really poke at things without having to repeatedly backspace and stretch weird to type / ;)
<heat>
:D
<heat>
stty erase ^H for major usability in the serial terminal
<heat>
wait, no
<heat>
you're running on your terminal emulator
<heat>
stty erase ^H is only needed in qemu's window stuff
<klange>
backspace is working fine under xfce terminal :)
<klange>
now what I really want is tab completion, is this dash?
<heat>
yes
<klange>
debian apparently has some build configuration with readline for it, but I suspect it's just rlwrap because I don't see any references to the actual readline (or libedit) in the upstream dash sources
<heat>
I've triggered a nightly with the new fix but it'll take a while to build everything :)
<heat>
dash supports readline
<heat>
iirc
<heat>
sorry, libedit
<klange>
ah, yes, it only supports libedit
<klange>
I might also recommend running `reset` on startup, the way QEMU spits out OVMF over serial puts things in a weird state with cursor display and background colors.
<klange>
but that is of course easily done by me, the user...
<geist>
yah that being said i think you came up with the solution that kills that screen reset thing that OVMF does
<geist>
it's an arg to qemu that among other thing stells the firmware to quit messing with the serial port
<geist>
though actually i think that was seabios
<heat>
hey hey hey
<heat>
who's up for some LTO'd disassembly debugging?
<klange>
Would you look at the time, I have to start work...
<moon-child>
while I still don't agree with the rust people, I understand them a lot better now. This is what they had to live with
<Mutabah>
There's a large number of rust design descisions that you can justify just be seeing how C++ did it (and not doing that)
<geist>
that being said move semantics are very powerful in lots of cases. it really helps
the_lanetly_052 has joined #osdev
<Clockface>
is there any reason to not use a.out nowadays?
<Clockface>
it seems pretty simple, so for some stuff it kind of seems good
<Mutabah>
ELF is just better? (More powerful, and not that hard to implement)
<Clockface>
isnt it more complex too?
<geist>
sure
<geist>
also ELF is cross platform, defined for pretty mcuh any arch you can think of
<geist>
and well supported by toolchains
<Clockface>
in this situation simplicity is more important than having lots of features
<geist>
okay. if that's important, then by all means that's a valid choice
<Clockface>
i originally wanted to do flat binaries but i still want a relocation table and separate code and data sections
<geist>
but in general the extra complexity of ELF is not that much more, and it's a very powerful and ubiquitous format
<geist>
also ELF handles shared libs very nicely, etc etc
<Mutabah>
I use two formats in my current project: A flat binary for the dynamic linker, and ELF everywhere else
<Mutabah>
(If I ever use dynamic kernel modules, the flat binary format will probably disappear)
<Clockface>
i want to use a.out for my kernel modules, and a "better" format for user programs like PE or ELF
<Clockface>
since kernel stuff doesnt seem to need as many features
<Clockface>
and its good to keep complexity out of it
<mrvn>
I only wish c++ would allow using move semantic when the compiler sees something is the last time a value is used.
<mrvn>
void foo(Bla &&bla) { blub(std::move(bla); } is just stupid.
jjuran has quit [Ping timeout: 248 seconds]
<mrvn>
I figure >90% of std::move could be figured out by a clever compiler
jjuran has joined #osdev
<Clockface>
has anyone ever tried ada for their OS, im still doing c
<Clockface>
it just seems neat
the_lanetly_052_ has joined #osdev
<Clockface>
you would probably end up doing stuff in c anyways actually
<Clockface>
nvm
<moon-child>
why?
<mrvn>
Clockface: you just need a bunch of primitives in asm or C for the hardware support.
<mrvn>
all the MMIO and atomic stuff for starters.
the_lanetly_052 has quit [Ping timeout: 248 seconds]
<Clockface>
i was just wondering about ada since its designed for stuff where you have to get it right the first time
<Mutabah>
Have you considered Rust?
<Clockface>
i would like to keep my penis, but yes
<Clockface>
i tried it
<Clockface>
its decent
<Clockface>
i still do C though since im used to it
* kof123
files away in notes "I would like to keep..." that's a keeper
<Mutabah>
Not really sure about the connection, so I'll ignore it
<moon-child>
Clockface: I meant, why would you have to do things in c if you wrote in ada?
gildasio has quit [Ping timeout: 268 seconds]
gxt has quit [Ping timeout: 268 seconds]
opal has quit [Ping timeout: 268 seconds]
gildasio has joined #osdev
gxt has joined #osdev
opal has joined #osdev
<Clockface>
good point
<Clockface>
low level stuff would be doable in assembly just fine
<Clockface>
actually
<Clockface>
ada can peek and poke memory like C can, with some extra steps
<Clockface>
so nothing C can do ada cant
<dminuoso>
That holds true for a lot of languages.
frkzoid has quit [Ping timeout: 255 seconds]
<dminuoso>
C is generally not used because its good at anything (it's really not, perhaps one of the poorest designed languages), its mostly used because "it's just what people use" or because of historical reasons.
<dminuoso>
C is particularly bad at dealing with memory because it frequently requires undefined behavior to do so (type punning), requires compiler extensions, or you have to explicitly copy things around, worry about lifetimes, and every pointer is just a memory bug waiting to happen, but since pointers are so ubiquitous, it's a language being bad at anything.
<matthews>
at least gcc and clang are reasonably okay at eliding the copies you do to get around the strict aliasing rules
zaquest has quit [Remote host closed the connection]
zaquest has joined #osdev
ZipCPU_ has joined #osdev
ZipCPU has quit [Ping timeout: 248 seconds]
ZipCPU_ is now known as ZipCPU
elderK has quit [Quit: Connection closed for inactivity]
gxt has quit [Remote host closed the connection]
gxt has joined #osdev
sortie has quit [Quit: Leaving]
sortie has joined #osdev
gxt has quit [Remote host closed the connection]
gxt has joined #osdev
scoobydoob has joined #osdev
scoobydoo has quit [Ping timeout: 268 seconds]
scoobydoob is now known as scoobydoo
<klange>
Missed the ELF convo because work stuff, but wanted to throw in my ¥2: None of ELF's complexity matters until you get to interesting things, and you really don't want to be doing those 'interesting things' with a.out - ELF was designed specifically because those 'interesting things' sucked with a.out.
foudfou has quit [Remote host closed the connection]
gelatram has joined #osdev
foudfou has joined #osdev
GeDaMo has joined #osdev
<mats1>
why isn't there a crypto signature in a standardised elf segment yet
<mats1>
is this really 2022
sortie has quit [Quit: Leaving]
sortie has joined #osdev
<kazinsal>
I suspect part of the answer is "none of the maintainers of operating systems that use ELF want to be responsible for maintaining code signing keys for userspace developers"
<kazinsal>
Microsoft and Apple can maintain their own big fancy codesigning databases because they're the centralized source of truth for it
<kazinsal>
And imagine from the point of view of the userspace developer, trying to keep your codesigning keys up to date and registered with half a dozen different Linux vendors, and FreeBSD, and OpenBSD, and NetBSD, and DragonflyBSD, and...
<kazinsal>
If I ever get back to my main osdev project I'll probably end up doing some codesigning stuff just for fun
gelatram has quit [Ping timeout: 252 seconds]
<kazinsal>
The emphasis in the FOSS community of "build your own software" negates a lot of the reason for codesigning binaries, despite the reality that the overwhelming majority of people who Linux (it's a verb, I assure you) just do binary updates from apt or yum for 99% of the software on their machine
<moon-child>
in particular, those packages (apt yum ...) _are_ signed
<moon-child>
which is better, since it ensures the safety of everything in the program. (What if I distribute a signed python binary from a trusted party, but pair it with a malicious python program?)
<moon-child>
if you're shipping binaries directly to end users by yourself, and you are in a position to care about codesigning, you are probably also specifically supporting a few linux distributions, and can have your own package repositories and (signed) packages for those distributions. (Google does this with chrome, for instance)
<moon-child>
s/few/couple/
<kazinsal>
Yeah, realistically, ELF doesn't have a signing mechanism because Yet Another Package Manager is the conventional place to put codesigning so that grognards who are obsessed with the purity of source-built end user software don't get upset about there being an optional signing extension to ELF that they may have to read
foudfou has quit [Remote host closed the connection]
foudfou has joined #osdev
<kazinsal>
I guess a better way to put it is that there is no portable mechanism for signing ELFs because the people who care about loading ELFs are not the people who care about the mechanism by which those ELFs get on your system
<kazinsal>
The kernel does not care how the ELF came to be, it just cares that the ELF is correct
<mrvn>
dminuoso: In C you can type pune via union usually. C++ has inventec bit_cast for it.
<mrvn>
Debian debs have had the mechanism for signed debs for decades and still it isn't used.
<mrvn>
and now you want to sign individual binaries?
<kazinsal>
Most sane codesigning environments sign the package and ensure the only way to install the software is through the package
<kazinsal>
Signing each individual binary is really more of a "this is a critical component and we need to prevent tampering" thing
<mrvn>
and if you can't trust the binary on your system then you can't trust the verifyier
<kof123>
"and now you want to sign individual binaries?" good point, now is the time to move to signing individual routines for maximum interceptor pattern </half-serious> </mel>
<kof123>
strike while the shield is down
<mrvn>
I could see signed binaries usefull for suid binaries or something limited. I would have to sign every time I run gcc
<bslsk05>
www.openbsd.org: signify: Securing OpenBSD From Us To You
<kazinsal>
Here's a paper about signing binaries and system distributions
<dminuoso>
mrvn: In C17 its undefined behavior.
<moon-child>
you can type pun with unions, but iirc there are weird compiler issues. Like, say you have union { int x; float y; } z; int *a = &z.x; float *b = &z.y;. You're supposed to be able to change z through a and observe the changes through b, but this doesn't work reliably
<moon-child>
imo it is better to just whack the compiler with -fno-strict-aliasing
<dminuoso>
There were some weirdly phrased provisions in footnotes that were not normative in earlier C standards about union type punning
<moon-child>
(you can also do your aliasing with memcpy)
<dminuoso>
But in C17 that was corrected and its properly undefined.
xenos1984 has quit [Quit: Leaving.]
<mrvn>
dminuoso: aliasing is a problem but otherwise compilers implement it so you can type pune
<moon-child>
dminuoso: what? I would be very surprised if aliasing through unions were made undefined. Can you provide a citation?
<mrvn>
moon-child: if you pass pointers to union members around that goes totally UB.
<dminuoso>
"When a value is stored in a member of an object of union type, the bytes of the object representation that do not correspond to that member but do correspond to other members take unspecified values."
<moon-child>
that says 'unspecified'
<moon-child>
not 'undefined'
<dminuoso>
undefined behavior needs not explicitly named.
<mrvn>
dminuoso: that's not what you do with type puning
<dminuoso>
If their values are unspecified, then using them yields undefined behavior
<moon-child>
no
<mrvn>
dminuoso: I think that's only unspecified behavior
<moon-child>
it means they have some value, and it's not specified what that value is
<dminuoso>
Ah I guess you are right
<klange>
Further, that means if you have two objects of different sizes, the the bytes that belong to one and not another are unspecified.
<mrvn>
anyway, the normal type puning is putting an uint64_t and a double into a union. Types with the same size.
<dminuoso>
You dont get any guarantees about what happens if you do.
<dminuoso>
Use compiler extensions, rather than pretending a union does what you want
<dminuoso>
They do exist.
<mrvn>
dminuoso: what compiler extension would allow type puning?
<moon-child>
the union does what you want. It's an intended, supported use case. The standard says unspecified because it doesn't want to lock itself into particular representations (or layout, in the case of structs)
<dminuoso>
moon-child: No it does not. "Unspecified value" would permit reordering reads after writes, because "whatever you may get is unspecified"
<moon-child>
but as soon as you are, say, peeking at the bits of a double, you are explicitly making assumptions about how that double is represented. Maybe you don't want to make such assumptions. But given you have made such assumptions, it doesn't matter how you get the bits
<dminuoso>
And that reordering is actually something that can and *does* happen if you viole this aliasing rule
<mrvn>
dminuoso: I don't think that is right. The compiler can't reorder access to different members of a union.,
<mrvn>
dminuoso: because those bits that do overlap are specified.
<mrvn>
for one thing
<dminuoso>
mrvn: Of course it can. Here's how the C standard will allow for it.
<klange>
The values of bytes that belong to both members _are specified_.
<dminuoso>
Imagine you write value X through member A, write value Y through member B, and read member A again. The compiler would be free to reorder things that you get value X back, not Y punned through A.
<mrvn>
dminuoso: no. since the overlapping bytes are specified to be affected
<mrvn>
dminuoso: unless A and B have no overlap, then sure. Don't do that.
<mrvn>
behaves as-if the compiler didn't reorder.
<mrvn>
Leaving aside the exact wording of the standard the intention of it is that if you have 2 structs with padding in a union and the padding in one struct overlaps a value in the other then the compiler can do whatever writing the the first struct. It doesn't have to preserve the padding bits or anything.
<dminuoso>
Mmm
<klange>
Or if you have two types in a union that are different sizes and you write to the big one then the small one, the bytes that are only in the big one could be _whatever_.
<mrvn>
sure, but compilers wouldn't do that
<mrvn>
they might if you have an array of the union and writing a SSE register to the array is faster
<klange>
If it's not volatile, I believe the compiler is allowed to ignore the fact you wrote to the big one if you just did that back to back, for example.
<dminuoso>
Let me dig again in the standard, but Im very confident that type punning through unions is not permissab;le
<mrvn>
klange: yes, that's the other thing this allows.
<mrvn>
dminuoso: it's not in the standard but it's implemented that way in every compiler I know.
<dminuoso>
Ah no I think how we arrive at this.
<dminuoso>
mrvn, start the other way around: This type punning would only be permissable if a provision existed in 6.5p7
<dminuoso>
`An object shall have its stored value accessed only by an lvalue expression that has one of the following types`
<dminuoso>
Look at the choices, and tell me which clause would be admissable.
<mrvn>
dminuoso: union { struct { char a, b; }; short s; }; does not give you access to the hi/low byte of s according to the standard. Because the standard doesn't say how the struct is layed out. For example.
<mrvn>
dminuoso: I already agreed with you that it's not covered by the standard. why are you still arguing?
<dminuoso>
mrvn: Right, but type punning through *that* would be allowed for a different reason
<dminuoso>
Fair enough.
<dminuoso>
moon-child: ^-
<dminuoso>
I think I was referring to the wrong person here
<mrvn>
dminuoso: what the standard explicitly covers is `union { struct Header { int h_magic; }; struct Msg1 { int m1_magic; int foo; }; struct Msg2 { int m2_magic; double bla; }; }; and accessing any of the magic.
<dminuoso>
mrvn: By which clause?
<klange>
It specifically lists an example like that.
<moon-child>
dminuoso: an aggregate or union type that includes one of the aforementioned types among its members (including, recursively, a member of a subaggregate or contained union),
<mrvn>
No idea. But the prefix of 2 types of a union that's identical may be accessed through either member.
<moon-child>
dminuoso: but anyway, going to bed now
<dminuoso>
moon-child: Nope! Thats not what you think it means.
<klange>
> One special guarantee is made in order to simplify the use of unions: if a union contains several
<klange>
structures that share a common initial sequence (see below), and if the union object currently contains
<klange>
one of these structures, it is permitted to inspect the common initial part of any of them anywhere
<klange>
that a declaration of the completed type of the union is visible.
<moon-child>
ah yeah, common initial sequence. You're even allowed to alias those
<mrvn>
^^ as klange quotes
<klange>
> Two structures share a common initial
<klange>
sequence if corresponding members have compatible types (and, for bit-fields, the same widths) for a
<klange>
sequence of one or more initial members.
<klange>
friggen pos pdf with line breaks tho
<dminuoso>
moon-child: That clause means if you have a `bool` in memory, and you have a union T that includes a member of type `bool`, you may have an lvalue of type T that points at that object
<dminuoso>
klange: That is no longer in C17.
<klange>
That is literally from the C17 document you linked.
<dminuoso>
Uh hold on
<klange>
That's where I copied it from.
<dminuoso>
*if* corresponding members have compatible types
<mrvn>
klange: passing pointers to members and then accessing the common initial sequence through them is not covered though.
<klange>
(Beyond the first member of a struct, fledgling demons live in padding and alignment, so anything else is unspecified.)
<dminuoso>
klange: A double and an int do not have compatible types.
<mrvn>
dminuoso: and nobody said so
<klange>
the fuck did i say anything about a double
<dminuoso>
│12:54:22 mrvn | dminuoso: what the standard explicitly covers is `union { struct Header { int h_magic; }; struct Msg1 { int m1_magic; int foo; }; struct Msg2 { int m2_magic; double bla; }; }; and accessing any of the magic.
<mrvn>
dminuoso: this was about my example with "int magic"
<dminuoso>
I was referring to this example.
<klange>
that doesn't have any doubles in the initial sequences
<klange>
and that is literally the example in the doc
<klange>
with differenet member names
<mrvn>
dminuoso: you can't access "foo" or "bla". Only the common "magic"
<klange>
the "initial sequence" is the shared int - h_magic, m1_magic, m2_magic
<klange>
The other members are incompatible because Msg2 might well have padding after the int and before the double while Msg1 has no padding and foo lives in that space, but all of those ints are compatible and in the same space
<mrvn>
dminuoso: that provision in the standard is explicitly there to allow tagged unions. The common initial sequence is used to figure out what type the union actually has and then you access the right type.
<mrvn>
right member
<klange>
Found the smoking gun.
<klange>
97)If the member used to read the contents of a union object is not the same as the member last used to store a value in the
<klange>
object, the appropriate part of the object representation of the value is reinterpreted as an object representation in the new
<klange>
type as described in 6.2.6 (a process sometimes called “type punning”). This might be a trap representation.
<dminuoso>
klange: footnotes are not normative
<dminuoso>
So its just a smoking toyguy.
<klange>
> Footnotes are
<klange>
provided to emphasize consequences of the rules described in that subclause or elsewhere in this
<mrvn>
dminuoso: footnodes are often references to other sections that are normative
<klange>
International Standard
<mrvn>
A side effect of that "initial sequence" is also that members in a struct can not be reordered.
<kazinsal>
If you do not read the footnotes, then wonder why your implementation does not work as described, you are Doing It Wrong (tm)
foudfou has quit [Remote host closed the connection]
<klange>
Footnotes are generally "we shouldn't need to say this because the main body of the spec should suffice to cover it, but just in case you needed a little extra help interpreting it..."
foudfou has joined #osdev
<dminuoso>
I have a counter rule that puts all of this back into UB land. 6.2.6p5 says "Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined."
<mrvn>
dminuoso: what has that got to do with anything in unions?
<klange>
That's for writing bytes to a double that produces a trap representation and then reading it back as a double and getting the trap.
<moon-child>
_if_ the stored value of an object has such a representation
<mrvn>
That's about how you interpret the bit patterns. Not what bit patterns are affected by reading/writing a union member
<moon-child>
but maybe you don't get a trap repr
<moon-child>
if (again) you make assumptions about how things are represented, then you may know that there are no trap representations for things you're interested in
<dminuoso>
Worse, it means if you write an int but reinterpret as a double you *can* get undefined behavior if the object representation is not a representation of the value of a doubule"
<klange>
If anything, that clause rather well says "hey if you write bytes into a union member that represent a trapping nan and then read it as the appropriate floating point type for that trap nan to manifest, it'll work!"
<dminuoso>
Its not necessarily about traps
<klange>
It's very specifically about traps.
<klange>
It is literally the sentence after the one you quoted: "Such a representation is called a trap representation."
<mrvn>
dminuoso: here is an example for you: union {long long x; int *p;} u; u.p = new int[2]; u.x++; *p; If you have tagged pointers on ARM that might trap.
<dminuoso>
mrvn: It would be undefined behavior, because the trap representation is read by an lvalue expression that does not have character type.
<klange>
_Only_ if the stored representation does not represent a value of the object type.
<mrvn>
dminuoso: no, it would be verry well defined. The implementation says pointers are tagged, you wroted a trapping representation so it will definetly trap.
gxt has quit [Ping timeout: 268 seconds]
<mrvn>
it's just not specified by the standard, it's specified by the implementation how pointers look.
gxt has joined #osdev
<klange>
That whole section is about how objects consist of bytes and some objects have equivalent sizes and those bytes can be interpreted as different types, and bytes that are perfectly valid representations for one type may not be for another - and _if they aren't_ the result is undefined.
gxt has quit [Remote host closed the connection]
gxt has joined #osdev
<mrvn>
All of that is just the standard saying it has no idea what the hardware will do if you feed it garbage.,
<mrvn>
if the bit patterns you feed it are a valid representation for the type you use then everything will work.
<mrvn>
(and valid includes represenations that will trap)
sweetleaf has quit [Quit: WeeChat 3.5]
<dminuoso>
At any rate, https://stackoverflow.com/a/36705613 gives a thorough attempt at interpreting the C standard to admit type punning. For me the final bit that simply disallows it, is that 6.5p7 gives an *exclusive* list by an object may have its stored value accessed. union member confusion is not among them.
<bslsk05>
stackoverflow.com: c - Is type-punning through a union unspecified in C99, and has it become specified in C11? - Stack Overflow
<dminuoso>
We dont even need to consider other sections, 6.5p7 alone makes it undefined behavior.
SpikeHeron has joined #osdev
ghee has joined #osdev
<dminuoso>
If for no other reason than q.r being an lvalue access of some object.
<dminuoso>
What is really important is that this is a final list that is *limited* to just the cases listed, because of the wording:
<dminuoso>
An object shall have its stored value accessed *only* by an lvalue expression that has one of the following types
<dminuoso>
We could perhaps understand as union type punning to be permissable only if 6.5p7 permits it
<dminuoso>
That is, if you do something like `union { int a; char b; }` setting it through a and reading it through b
<dminuoso>
However, GCC explicitly allows for it (see documentation on -fstrict-aliasing). I do not know about clang here.
gog has joined #osdev
heat has joined #osdev
nyah has joined #osdev
gog has quit [Ping timeout: 248 seconds]
<mrvn>
dminuoso: what abour rvalue access?
<mrvn>
Originally in C a union did not have to have members even share bytes.
<mrvn>
The common initial sequence has made that mandatory.
<dminuoso>
mrvn: What kind of rvalue are you thinking of?
<dminuoso>
Besides, rvalues cannot access an objects stored value
<dminuoso>
(sort of by definition)
<dminuoso>
If it could, it would be an lvalue.
<mrvn>
dminuoso: return value from a function?
<dminuoso>
Im not sure I follow
<mrvn>
why can an object only have its value accessed by an lvalue expression?
<klange>
foo().bar is, for example, entirely valid but not an lvalue
<dminuoso>
Why would it not be an lvalue?
<klange>
Because foo() is a postfix expression.
<dminuoso>
"An lvalue is an expression (with an object type other than void) that potentially designates an object;"
<mrvn>
klange: I think in C that is still an lvalue expression
<dminuoso>
klange: that is irrelevant in C
<mrvn>
unlike C++
<dminuoso>
If it can identify an object, its an lvalue expression in C.
<klange>
> If f is a function returning a structure or union, and x is a member of that structure or union, f().x is a valid postfix expression but is not an lvalue
<mrvn>
klange: but is it an lvalue expression?
<dminuoso>
klange: okay yeah that remark is very surprising.
<dminuoso>
But again, examples and footnotes are not normative.
<dminuoso>
If you can cite a normative definition from which you can infer that remark, Id be interested
<bslsk05>
gcc.gnu.org: Subscripting (Using the GNU Compiler Collection (GCC))
<dminuoso>
What I find really interesting, is that if this was true, foo().bar would *not* be allowed to access the objects stored value.
<dminuoso>
Unless there's some other provision that does not consider whatever this refers to as an object.
<mrvn>
dminuoso: So where in the standard is "f().x" covered? And if that is an lvalue expression then why can't is write "&(f().x)"?
<mrvn>
s/can't is/can't I/
<dminuoso>
mrvn: No clue, but even if there was such a provision, it would be in direct conflict with 6.5p7
<dminuoso>
An object shall have its stored value accessed ____only____ by an lvalue expression that has one of the following types
<dminuoso>
Emphasis added by me
<dminuoso>
But this is a product of a humans, it wouldnt be surprising if there were contradictory phrases.
<klange>
I want to say that the _object_ is the union (or struct) and the access happened when it was returned, not when the member was referenced as a postfix expression.
<dminuoso>
As per 6.5p1 the object would be that field of a union you get back
<klange>
And by the same logic, type punning is legal because the _object_ was already accessed by an lvalue of a union that contains the type used to store the value, even if the new member reference doesn't.
<mrvn>
In C an "lvalue" is an "object locator". Which I would take as meaning I can use "&" on it.
<dminuoso>
klange: "of a union that contains the type" doesnt mean what you are thinking of
<klange>
"an aggregate or union type that includes one of the aforementioned types among its members" is the exact phrasing
<dminuoso>
klange: That portion just roughly says "you may pun an existing `bool` object through a `union that has a member of type bool`
<dminuoso>
An object shall have its stored value accessed only by an lvalue expression that has [the following type]: an aggregate or union type [...]
<dminuoso>
i.e.:
<dminuoso>
a double object shall havce its stored value accessed [..] by an [..] expression that [is a union type]
<dminuoso>
meaning if you have `typedef union { int a; bool b; } T`
<dminuoso>
You may do something like: *(T *) some_bool_ptr
<mrvn>
dminuoso: does that section maybe only apply to writing a value?
<dminuoso>
mrvn: No, its very specifically only about reading.
<dminuoso>
"its [already] stored value accessed"
<mrvn>
but clearly values can be read via rvalue.
<dminuoso>
Yeah, I was quite surprised by that earlier
<dminuoso>
I think its just contradictory
<mrvn>
That's the whole point of rvalues. Things you can only read.
<dminuoso>
One might, perhaps, infer that therefore there's no *object* here
<dminuoso>
If that was the case, it would suggest type punning was completely and utterly allowed via rvalues
<dminuoso>
But I think what's really the case here, is that the standard is badly written and has contradictions
<klange>
The thing with aggregate and union types... if you store a value for a field of a struct, and then (entirely legally) use a 'character type' to alias _the struct as a whole_, are you accessing the "stored value" of the object of the field you set? I think this is the situation that bulletpoint is intended for, and the answer is "yes".
<mrvn>
klange: more difficult question: If you have a pointer to a union containing (among others) an int and pointer to int and you access other members of the union do they alias?
<mrvn>
I believe they do because any weirdness is only unspecified but not undefined.
<dminuoso>
klange: Its also not quite clear what the object is when storing via union. That is, whether the member field is the actual object or the union itself.
<dminuoso>
I have a few paragraphs that let you interpret it either way
<mrvn>
dminuoso: In c++ it's the member
<dminuoso>
Did you know that in C++ constexpr can be made non-constant in a standard compliant manner? :)
<mrvn>
obviously.
<mrvn>
well, in c++20
<dminuoso>
What do you mean?
<dminuoso>
I meant you can concoct a program, such that `int main () { constexpr int a = f (); constexpr int b = f (); static_assert (a != b, "fail"); }` will fail at that assertion.
<bslsk05>
web.archive.org: Non-constant constant-expressions in C++
<mrvn>
hmm, wait, how?
<dminuoso>
^-
SpikeHeron has quit [Quit: WeeChat 3.6]
<mrvn>
evil. You aren't changing a constexpr though, you are evaluating 2 different constexpr (while modifying the evaluation environment)
<mrvn>
meta-writing to the constexpr
<dminuoso>
"You aren't changing X. It's just that these two subsequent uses of X are different things"
<dminuoso>
Observationally, I do not think this differentiation is useful.
<mrvn>
I still don't get how `bool B = noexcept (flag (0)),` will give false when the function hasn't been defined.
SpikeHeron has joined #osdev
<mrvn>
"(1) will set B = true if flag(0) is a constant-expression, otherwise B = false, and;" How?
<dminuoso>
I think "is a constant-expression" is poorly phrased
SpikeHeron has quit [Ping timeout: 256 seconds]
<mrvn>
The magic seems to be that even though "constexpr int flag (int);" means flag is always a constexpr that does not hold true when flag isn't defined yet. A forward declaration fails the "noexcept()
<mrvn>
dminuoso: do you know that a constexpr isn't constant evaluated when you pass it non constexpr arguments?
<dminuoso>
That sounds vaguely familiar, yes.
<mrvn>
otherwsie you couldn't write: int x = 1; int t = flag(x);
<dminuoso>
I dont think this is very surprising, I suppose constexpr is just an ability to evaluate it at compile time, not a guarantee.
<mrvn>
hmm, without a definition of "flag" the "noexcept()" can't actually tell if the function throws an exception or not.
<mrvn>
I want to have everything constexpr because then I have no UB.
<mrvn>
plus all programs would be so much faster.
<dminuoso>
It's interesting, when I started osdev, I switched to C++ to gain some compile time guarantees for a better experience. That road eventually led me to Haskell. :)
<dminuoso>
But sadly Im not writing a kernel in Haskell - but I should!
<dminuoso>
mrvn: I think what people are *really* after is purity, not necessarily compile-time.
<mjg>
c++ compile time guarantees?
<mjg>
you mean that it is going to take a long time? :)
<dminuoso>
Well I just cared for tracking facts in the type system
<mrvn>
you mean a linear type system?
<heat>
i want kenrel
<heat>
kenrel run code
<heat>
unix code
<heat>
like 70s computr but now
<mjg>
unicode
<heat>
16 bit unicode yes
<dminuoso>
mrvn: No I dont care for linear types. :p
<dminuoso>
Uniqueness types yes, linear types no.
<heat>
mjg, but really you should try and build Onyx
<heat>
there's a super stark difference between "code I wrote" and "code I wrote that uses 3rd party libraries"
<heat>
(in the C++ of course)
gog has joined #osdev
<mrvn>
dminuoso: you can always use lambdas
<mjg>
heat: you got a bitcoin miner in there
<heat>
no that's just gtest
<heat>
let it compile
<heat>
:D
<mjg>
y tho
<heat>
why does it take so long to compile? idfk
<heat>
ask goog
<heat>
the way C++ people get a boner once you mention HEADER-ONLY LIBRARIES is astonishing
<heat>
because it makes everything so much slower
<heat>
I also have a header-only json parser in there
<heat>
guess what: it's also dogshit slow to compile
<mjg>
i'm aware of gtest, it is part of freebsd :S
<mjg>
it kept blowing up on my 2G vm
<mjg>
amazing
<heat>
I use gtest and gbenchmark, they're pretty good but so damn slow to compile
<klange>
My json parser compiles in... 0m0.225s
<heat>
also what kind of fake unix depends on C++
<heat>
jeez
<mrvn>
That's the problem with templates. you can't put them in their own compilation unit.
<klange>
My other JSON parser compiles in 0m0.002s.
<mrvn>
c++ lacks polymorphic functions.
<mrvn>
Maybe I should write a C++ paper for polymorphic functions.
<heat>
google makes up most of my userspace compile time
<heat>
using STL also blows up your compile time a bit
<klange>
I think the longest part of my build is... building my compiler/interpreter, amusingly enough.
<klange>
Just took a ridiculous 12 seconds here.
<klange>
But... I am playing FFXIV simultaneously, that probably slows things down a bit...
<klange>
The next longest is probably the editor.
<heat>
your things compiles super quickly
<heat>
real 0m8.653s
<heat>
for bim + kuroko
<klange>
That "other JSON parser" is the one written my Python clone; the bytecode compiler is super fast (waaaay faster than CPython's, for sure). The first one is the C one so that 0.225s is a realistic number.
<heat>
8 threads
<klange>
Bim is a single source file, and for the OS builds I throw all of the C sources of Kuroko into one gcc invocation, so neither can be threaded properly.
<heat>
when are you taking my meson patch
<heat>
it builds the whole of kuroko in less than 3.2 seconds
<klange>
Irrelevant as I don't use any of the external build system in the OS builds.
the_lanetly_052_ has quit [Ping timeout: 256 seconds]
ghee has quit [Quit: EOF]
Matt|home has quit [Remote host closed the connection]
foudfou has quit [Remote host closed the connection]
foudfou has joined #osdev
gxt has quit [Remote host closed the connection]
gxt has joined #osdev
matt__ has joined #osdev
matt__ is now known as freakazoid333
<dminuoso>
mrvn: It wasnt about that.
GeDaMo has quit [Read error: Connection reset by peer]
<dminuoso>
mrvn: For me osdev was just a roadtrip for me to understand what I majorly disliked about the programming languages I knew at the time.
GeDaMo has joined #osdev
gog has quit [Read error: Connection reset by peer]
gog` has joined #osdev
skipwich has quit [Quit: DISCONNECT]
skipwich has joined #osdev
skipwich has quit [Read error: Connection reset by peer]
skipwich has joined #osdev
Gooberpatrol66 has quit [Ping timeout: 244 seconds]
eroux has joined #osdev
<heat>
dminuoso, i have slowly realized I hate them all
eroux_ has quit [Ping timeout: 248 seconds]
<heat>
C++ is the least worse one if done correctly
<dminuoso>
I found my peace with Haskell. :)
<heat>
despite it being deeply flawed, I really value RAII and classes
<heat>
templates are OK in moderation
<heat>
i would be up for some rust but its slow to compile and im scared
<heat>
it also brings in a hard dependency on LLVM (for now)
gog` is now known as gog
Gooberpatrol66 has joined #osdev
Andrew is now known as WaxCPU
freakazoid333 has quit [Ping timeout: 255 seconds]
frkzoid has joined #osdev
matt__ has joined #osdev
frkzoid has quit [Ping timeout: 248 seconds]
wootehfoot has joined #osdev
<ddevault>
regarding the earlier discussion on page allocators, I ended up sticking with a free list but extending it to be able to allocate continuous pages
<ddevault>
it will probably get fragmented but it's enough for onw
<geist>
Yah that’s not a bad strategy. In general contig allocations aren’t as useful as you think, except when you need me
<heat>
again, i think it depends on your design
<heat>
it's crucial to linux's mm for instance
<geist>
In the long run a perfectly fragmented pmm and the need to defrag it will probably rear its head, but that’s usually much past where most hobby OSes go
gxt has quit [Remote host closed the connection]
foudfou has quit [Remote host closed the connection]
<geist>
Exactly, but then that’s very advanced stuff, most hobby OSes dont get that far
foudfou has joined #osdev
gxt has joined #osdev
<clever>
which reminds me, i was just commenting on an rpi forum thread, about the linux CMA heap being fragmented
<geist>
Not that you shouldn’t shoot for it, but it’s more that that sort of thing probably requires serious work load, etc that most people just dont have time enough to get to
<clever>
problems allocating 182mb objects, that must be physically contiguous
<geist>
Yah, that’s usually where it rears its head: stupid hardware with stupid contig requirements
<clever>
there is a 512mb heap just for that purpose, but its still fragmenting
<geist>
Yup we have something like that on zircon and its also indeed annoying
<clever>
palmos and the rpi firmware have a solution to that, a relocatable heap
<clever>
where the kernel can relocate heap objects to defrag it
<clever>
but that feature was lost when moving all of the memory management to the linux side of things
<geist>
surprised you mentioned palmos. Did someone port the palmos classic to rip?
<geist>
Rpi?
<clever>
my dad had a treo 650 phone years ago
<clever>
and i tried coding for it
<clever>
and it happens to have the same relocatable heap, because it lacked an MMU
<clever>
every program had to share a single address space
<heat>
yo geist
<heat>
what do you know about io request packets
<heat>
I wanted to get something like that going in my OS
<geist>
Probably about as much as you
<heat>
shoot
<heat>
finally something you don't know anything about
<heat>
amazing
<geist>
As in seems like a good idea, but i dont know the extent of the inevitable downsides
<clever>
geist: i did also find a nommu build of linux, that could run on the treo 650, along with a bootloader app, one advantage of a no-mmu os, is that any app can just turn irq's off at any time, and chainload a new os
<clever>
but then linux itself needs a special libc, because fork() cant work, only vfork()
matt__ is now known as freakazoid333
<heat>
my renewed storage stack design was gonna be something like page cache -> filesystem (where I would craft an IRP like thing) -> block device mini-stack (may have crypto, whatever in the middle) -> io-queue (generic thing to serve io requests, represents a single hw queue) -> driver
<heat>
all async
<heat>
then at the page cache you would just wait on the page(s) you requested to be read
<clever>
geist: oh, now i see why those numbers are so huge, it was an rgb888 image, at bloody 9152x6944, lol
<heat>
clever, linux doesn't need a special libc for nommu
<clever>
heat: does fork just invisibly call vfork then?
<heat>
no
<heat>
that's incorrect
Matt|home has joined #osdev
<heat>
but no libc functionality actually requires fork
<jjuran>
heat: Yeah, slow compile times turned me off of header-oriented programming. Now I aim for short translation units, 20th-century Lakos-style.
<jjuran>
klange: Does playing FFXIV send your compile times heavensward?
freakazoid333 has quit [Ping timeout: 255 seconds]
<jjuran>
clever: fork() can be done, but it's clunky.
<heat>
fork cannot be done unless you swap the two processes
<clever>
jjuran: how?
<clever>
yeah
<jjuran>
That's how MacRelix does it. Back up all the memory regions of each process sharing address space, and swap between them
<heat>
that's how the original UNIX used to do it
<clever>
yeah, that could work, but vfork is just faster, for the same reason vfork was originally made
wootehfoot has quit [Ping timeout: 268 seconds]
<jjuran>
Oh yeah, vfork() is preferred as long as its semantics are adequate
<clever>
yep
<clever>
original mmu vfork, was to deal with the lack of CoW in the kernel, so the child would temporarily share the parent pages, full r/w but no touchy
<clever>
and nommu vfork is because you cant isolate, so its sharing everything always
<heat>
vfork is still way faster than COW
<heat>
single atomic ref inc vs copying a whole lot of page tables, vm structs, TLB flushes, yadda yadda
<heat>
only issue: it's a blocking operation
FreeFull has joined #osdev
<clever>
hmmm, was going to offer a cheat, but to properly do CoW, you must tag every page as ro
<clever>
so you have to at least modify one set of paging tables
<heat>
clone(CLONE_VM) doesn't block though
<heat>
clever, what cheat?
<clever>
was thinking, sharing parts of the paging table itself between procs
<clever>
but for CoW to work, the pages must be read-only, in both procs
<clever>
so you need to modify the entire paging table for the proc, and then maybe you can share the tables
<heat>
sharing page tables sounds super complex for everyone, for not enough gain
<clever>
and dup tables as you begin to dup pages
<clever>
yeah
<clever>
basically, you would need to treat an entire 1tb chunk of the virtual space, as a single CoW'd block
<clever>
and reuse the whole paging table tree under that
gog` has joined #osdev
<clever>
and when you need to copy, you un-merge that layer of the paging tables, and recursve one layer down
<heat>
but as soon as you fault something in, your idea comes crashing down
<heat>
and it would indeed require everything to be RO, and then it also breaks the A bit
<clever>
yeah, faulting anything in, will also require copying some page tables
ghee has joined #osdev
jafarlihi has joined #osdev
<jafarlihi>
Guys, how do I git gud? I read C++ books all day. Is 10000 hours rule real?
<jafarlihi>
I tried to implement GraphQL for cpp recently, done with lexer and parser but execution totally got me on my ass
<jafarlihi>
It's just so hard to sink into these big codebases
<bslsk05>
github.com: original-bsd/vfs_cache.c at master · weiss/original-bsd · GitHub
<heat>
has a lot of comments explaining how things work
<heat>
still has the UNIX/BSD syndrome of havingfuncwtsnkcs
<mjg>
* Invalidate a all entries to particular vnode.
<mjg>
* We actually just increment the v_id, that will do it. The entries will * be purged by lookup as they get found. If the v_id wraps around, we * need to ditch the entire cache, to avoid confusion. No valid vnode will * ever have (v_id == 0).
<mjg>
fucking copy paste
<mjg>
here is the best part: some of this bullshit remains in openbsd to this very day
<mjg>
extra points for wasting 16 bytes to store 2 NULL pointers
<mjg>
linux is full of this kind of crap all over
<moon-child>
thanks, I hate it
dude12312414 has joined #osdev
<heat>
that is very cute but you're fucking yourself over
<heat>
play stupid games win stupid prizes
<mjg>
just sayin that linux is not better than bsd
<mjg>
the wtf is strong in both codebases
<heat>
i can't really read bsd code because a good chunk of it is obfuscated beyond belief by HACKERS
<mjg>
in their defense, it looked fucking clean on LSD
<mjg>
i don't know what the author of thea bove was ingesting tho
<mjg>
definitely not a book on smp
<heat>
vn_rdwr
<heat>
and this is already super fucking readable compared to vnrdwr
<heat>
which I asusme must have existed somewhere in this time-space continuum
<heat>
and before you say "oh no, symbols had character restrictions stupid young fella", there's a call to vm_map_protect right after this
<mjg>
the vm was copied from mach
<mjg>
i.e. they did not write it
<heat>
thank god?
<heat>
mtod()
<heat>
this is, in fact, not a function that gives you the message of the day
<mjg>
i guess you don't know how much of a nightmare mach vm is
<heat>
almost though
<mjg>
i know only the tip of the iceberg and i'm already terrified
<mjg>
in short, it is trying to fuck you over a lot
<mjg>
it has this concept of object chains, where you can handle copy on write adn similar
<mjg>
the issue is if you fork -> fork -> fork you keep making the chain longer
<mjg>
so there is machinery to try to collapse it
<mjg>
and do some other stuff
<mjg>
the end result is that any time you access an object you have to check it's identity
<moon-child>
tbf you probably shouldn't fork -> fork -> fork
<mjg>
... because the thing you are accessing now might have been freed and reused
<moon-child>
and didn't macos deprecate any use of fork not immediately followed by exec anyway?
<mjg>
moon-child: the problem happens already, i'm just ilustrating why the fuck-you-over mechanism is there
<heat>
deprecate? probably
<moon-child>
ok
<heat>
but mach vm heavily predates macOS
<heat>
at least the modern one :P
<heat>
why did everyone copy code from each other back then
<moon-child>
looked at butterfly scheme source code a bit ago
<heat>
i thought that was reserved for firmware engineers
<moon-child>
tried for a few minutes to get it compiling on modern systems before giving up. But a few mach calls I didn't know what they did I was able to find macos documentation for
<moon-child>
(butterfly scheme was some parallel computing research project from I think the late 80s-early 90s?)
<heat>
mjg, why would you not just... you know... go to the root of the chain?
<mjg>
it looks like this, you fork and get a pristine vm_object + backing object from the parent
<heat>
i know
<heat>
i have implemented that logic
<mjg>
right
<mjg>
anyhow, it is utter terrible
<heat>
fuck off you're utter terrible
<heat>
my code is flawless
<mjg>
i'm talking about the bsd here
<mjg>
but given your reaction it seems the sentence has wider application
<mjg>
not that i'm judging1
<mjg>
for real though, there is significant lock contention on this bullshit and making it lockless runs into bizzare corner cases
<mjg>
as the vm can fuck everything up from under you despite you having a ref on the object
<mjg>
as in the object can transition into dead state if you don't hold the lock
<mjg>
then there mind boggling rules about how to secure access to a page
<mjg>
where even shared access can get the page whacked
<mjg>
like wtf
<mjg>
LSD, as i said
<heat>
how do you not chain things?
<heat>
teach me sensei
<mjg>
i don't have a good solution to not chain stuff, but netbsd claims to have one
<mjg>
see the uvm paper by cranor
<mjg>
my work around to this bullshit (to be implemented) is sequence counters
<mjg>
i'm going to wrap all destructive ops with it
<heat>
so why did freebsd not steal uvm
<mjg>
way before my time man
<mjg>
from what i know in general about that period likely reasons are
<mjg>
1. uvm is crap
<mjg>
2. the freebsd approach is crap
<mjg>
3. the freebsd dude doing the work hated the guts of the netbsd dude
<mjg>
for point 2, i mean it is crap but it was not realized
<Matt|home>
...
<mjg>
people will go to great lengths to not implement a good idea if the wrong person had it
<mjg>
for real
<heat>
swear to god bsd people are weird
<mjg>
you think linux are not?
<heat>
it's like code communism
<heat>
everyone uses everyone else's code
<heat>
until they don't (when it's important!)
<mjg>
seriously man, go work for a bigcorp for few years
<Matt|home>
i really liked freebsd.. used it as my main desktop for a while. then ubuntu became more convenient finally. i still say it's probably the best open source OS for a file server
<mjg>
it is amazing what kind of bullshit goes on there
<heat>
alright what's your story matthew garrett
<mjg>
Matt|home: it is ok
<mjg>
Matt|home: you do know that openzfs is primarily developed on linux though? ;)
<Matt|home>
right now im praying to the tech gods that the episodes im burning to DVD will be recognized by my mom's dvd player with this weird software i've never heard of before im using to burn it..
<Matt|home>
nah i don't keep track but there's typically a lot of crossover in the open source communities
<Matt|home>
i have a personal fondness for BSD systems, but that's just uh
<Matt|home>
what's the word
<Matt|home>
nostalgia
<mjg>
heat: how about this little tidbit: someone important(tm) had a stupid idea and i called them out, then he started saying that "we" (whoever might have been included) determined my objections are bs
<mjg>
heat: so he went through with it
<mjg>
heat: few months later someone posted a review which fixed all the bullshit i pointed out
<heat>
what corp
<mjg>
heat: and he accepted it
<heat>
and when
<mjg>
i'm gonna protect the guilty on this one
<Matt|home>
fun fact: i have ripped out a brand new xbox 360 DVD and cover art to replace with my burned disc.
<Matt|home>
can anyone guess which game it was, that i stomped on scratched and spit on
<Matt|home>
NOOOOOOO
<mjg>
heat: general point being that merit has nothing to do with what's getting implemented
<Matt|home>
!!! fine.. fine.. fine.. im just gonna go cry in a corner..
<heat>
I would like to guess but I'm taking too long to get a troll answer
<heat>
Barbie and Her Sisters: Puppy Rescue
<mjg>
heat: how about this tidbit. department's director used to be a programmer and wrote an incredibly insecure piece of code
<mjg>
when i got there i pointed out all the vulns not knowing the authorship
<mjg>
then he kept claiming none of this can be true
<mjg>
cause you know, how the almighty can pull off something so bad
<mjg>
[issues were boiling down to walking unprivileged users home dirs as root and doing stuff in a racy manner]
frkzoid has quit [Ping timeout: 256 seconds]
<heat>
idk man
<heat>
sounds like you worked at the wrong company
<heat>
or with the wrong people
<mjg>
this is the standard man
<heat>
cloudflare is chill
<heat>
everyone is more than nice
<mjg>
people tend to be nice if you don't call them out
<mjg>
i don't know cloudlare, it may be majority is competent
<heat>
maybe there just are a lot of self-centered assholes at $corp
<heat>
a good chunk of the work done in the last 2 months in my team was to tear down things the project lead did
<heat>
and I didn't see any bullshit breakdown
<heat>
most people I've personally talked to (both at CF and Tianocore for instance) are quick to admit flaws in their stuff
<mjg>
generic "we could have done it better" is also the standard. try to point out the supposed good idea is a non-starter though
<mjg>
in particular there is type of a person who treats people as follows:
<mjg>
1. if they perceive you as below them, they are super nice
<mjg>
2. if they perceive you as above them, again super nice
<mjg>
3. if they see you as a competition they lose their shit
<mjg>
if you are in the 1st category things go really bad if starting to look like you don't belong there
<mjg>
if it's
<mjg>
how about this:
<mjg>
i had 2 managers at 2 companies who claimed the workplace is fucking great
<mjg>
and would never trade it for squat
<mjg>
both suddenly quit :D
<mjg>
i managed to catch one, he admitted it's all crap, he just does not shit on the company while he is there