Age | Commit message (Collapse) | Author |
|
Introduce ucode precompilation support
|
|
Introduce a new default enable CMake option "COMPILE_SUPPORT" which
allows to disable source code compilation in the ucode interpreter.
Such an interpreter will only be able to load precompiled ucode files.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Introduce new command line flags `-o` and `-O` to write compiled program
code into the specified output file
- Add support for transparently executing precompiled files, the
lexical analyzing and com,pilation phase is skipped in this case
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Move source object pointer into program entity which is referenced by
each function
- Move lineinfo related routines into source.c and use them from lexer.c
since lineinfo encoding does not belong into the lexical analyzer.
- Implement initial infrastructure for detecting source file type,
this is required later to differentiate between plaintext and
precompiled bytecode files
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Instead of storing constant values per function, maintain a global program
wide list for all constant values within the current compilation unit.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
- Introduce a new "program" entity which holds the list of functions
created during compilation
- Instead of storing pointers to the in-memory function representation
in the constant list, store the index of the function within the
program's function list
- When loading functions from the constant list, retrieve the function
by index from the program entity
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
lib: implement uniq() function
|
|
The uniq() function allows extracting all unique values from a given input
array in an efficient manner. It is roughly equivalent to the following
ucode idiom:
let seen = {}
let unique = filter(array, item => !seen[item]++);
In contrast to the code above, `uniq()` does not rely on implicit
stringification of item values but performs strict equality tests internally.
If equivalence of stringified results is desired, the following code can
be used:
let unique = uniq(map(array, item => "" + item));
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Platform neutral doubles
|
|
When concatenating strings, avoid allocating three times the required
memory in the worst case. Instead of first allocating the string
representations of the operands followed by the memory for the final
string, allocate a string buffer and print the operands into it. This
will grow the target memory as needed and avoid redundant internal
copies of the involved strings.
Also handle the special where the final string fits into a tagged
pointer and deal with it accordingly.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Use uc_pack_double() and uc_unpack_double() from core to avoid unnecessary
code duplication.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Import the binary64 double packing routines from the struct module and
use them to store numeric double values in a platform agnostic big
endian format.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
treewide: rework numeric value handling
|
|
- Parse integer literals as unsigned numeric values in order to be able
to represent the entire unsigned 64bit value range
- Stop parsing minus-prefixed integer literals as negative numbers but
treat them as separate minus operator followed by a positive integer
instead
- Only store unsigned numeric constants in bytecode
- Rework numeric comparison logic to be able to handle full 64bit
unsigned integers
- If possible, yield unsigned 64 bit results for additions
- Simplify numeric value conversion API
- Compile code with -fwrapv for defined signed overflow semantics
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
fs: implement fdopen(), file.fileno() and proc.fileno()
|
|
Implement support for opening existing file descriptors as well as acquiring
the descriptor number from open process and file handles.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
ubus: add support for async requests
|
|
Introduce a new ubus.defer() method which initiates asynchroneous requests
and invokes the completion callback passed as 4th argument once the reply
is received.
This allows multiplexing mutliple ubus requests with the same ucode VM
context / the same uloop event loop.
In case the ucode context is not running under an active uloop, the ubus
module will spawn uloop itself once the first asynchroneous request is
launched and terminate the loop once all pending requests finished.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Introduce a new, lazily allocated value registry which can be used by C
code to store values which should not be garbage collected.
The registry is a plain ucode object internally and treated as GC root
but not exposed to ucode script code, this allows it to retain references
to values which are otherwise completely unreachable from ucode scripts.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Fix various misspelling of "resource".
This commit changes the exported libucode ABI.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
No functional changes.
Fixes: ff52440 ("treewide: consolidate typedef naming")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The prevents garbage collecting properties which are stored in resource
value prototype objects.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Allow querying object properties on resource values. A resource value may
have a prototype object set whose properties should be enumerable.
Support that use case in the VM.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The nl_recvmsgs() logic in uc_nl_request() incorrectly stopped reading
the socket before the netlink ACK message was handled for non-multipart
replies.
This caused subsequent requests to incorrectly receive the ACK of the
previous request, leading to a failure to receive the actual reply.
Fix this issue by continue reading the socket until either the finish
callback for multipart (dump) messages or the ack callback for non-
multipart messages was received.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Add three new functions `dirname()`, `basename()` and `lsdir()`.
The `basename()` and `dirname()` functions behave like their libc
counterparts and return the filename and directory portion of a
given path respectively. If the path argument is missing or not
a string, null is returned.
Examples:
dirname("/usr/lib") -> "/usr"
dirname("/usr/") -> "/"
dirname("usr") -> "."
dirname("/") -> "/"
dirname(".") -> "."
dirname("..") -> "."
basename("/usr/lib") -> "lib"
basename("/usr/") -> "usr"
basename("usr") -> "usr"
basename("/") -> "/"
basename(".") -> "."
basename("..") -> ".."
The `lsdir()` function returns a sorted array containing the names
of all entries within the given directory path, without the common
"." and ".." entries. If the given path is not a directory, cannot
be opened or if another system level occurs, null is returned and
`fs.error()` can be used to query details.
The function takes an optional second argument which may be either a
regular expression value or a string. In case a regular expression
is given, each directory entry is matched against it. In case a
string is provided, it is treated as wildcard (glob) pattern and
only directory entries matching the pattern are considered.
Examples:
lsdir("/sys/class/net") -> [ "eth0", "lo", "wlan0" ]
lsdir("/proc", /^[0-9]+$/) -> [ "1", "4", "12", ... ]
lsdir("/sys/class/block/", "sd?3") -> [ "sde3", "sdf3" ]
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Extract the wiphy index from the response message and use it to select
the item to merge the fragment information into.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Fix instances of misspelled "resource".
This commit breaks the exported libucode ABI.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
The "align" pragma was accidentally renamed while refactoring the
original module code.
Fixes: 402f603 ("lib: introduce struct library")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
lib: introduce struct library
|
|
Introduce a new "struct" library which is a port of the Python 3.10 struct
module with a reduced set of API functions. It supports the same format
patterns and conversions while providing the following methods:
struct = require('struct');
buf = struct.pack("fmt", args...);
values = struct.unpack("fmt", buf);
struct_inst = struct.new("fmt");
buf = struct_inst.pack(args...);
values = struct_inst.unpack(buf);
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
While most source files contain the license text in their header, make
the repository license explicitly known by putting it here.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
lib: introduce resolver library
|
|
Subsequent requires of the same module returned the cached module instance
without increasing the refcount, leading to use-after-free on VM tear down
or garbage collection cycles.
Solve this issue by properly incrementing the refcount before returning
the cached module instance.
Fixes: #25
Fixes: 96f140b ("lib, vm: ensure that require() compiles modules only once")
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
This adds a simple, UDP-only DNS resolver library mimicking the operation of
the extended busybox nslookup applet.
Simply querying a domain name will perform A + AAAA resolving by default:
# ucode -mresolv -Rs 'printf("%.J\n", resolv.query("example.com"))'
{
"example.com": {
"A": [
"93.184.216.34"
],
"AAAA": [
"2606:2800:220:1:248:1893:25c8:1946"
]
}
}
Passing IP addresses will automatically perform PTR requests:
# ucode -mresolv -Rs 'printf("%.J\n", resolv.query("8.8.8.8"))'
{
"8.8.8.8.in-addr.arpa": {
"PTR": [
"dns.google"
]
}
}
# ucode -mresolv -Rs 'printf("%.J\n", resolv.query("2001:4860:4860::8888"))'
{
"8.8.8.8.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.6.8.4.0.6.8.4.1.0.0.2.ip6.arpa": {
"PTR": [
"dns.google"
]
}
}
Additional options for query type and nameserver selection can be passed via
a second optional options dictionary:
# ucode -mresolv -Rs 'printf("%.J\n",
resolv.query([ "openwrt.org", "example.org", "doesnotexist.tld" ], {
type: [ "A", "AAAA", "MX" ],
nameserver: [ "1.1.1.1", "8.8.4.4" ],
timeout: 5000,
retries: 2,
edns_maxsize: 4096
}))'
{
"openwrt.org": {
"A": [
"139.59.209.225"
],
"MX": [
[
10,
"util-01.infra.openwrt.org"
]
],
"AAAA": [
"2a03:b0c0:3:d0::1af1:1"
]
},
"example.org": {
"A": [
"93.184.216.34"
],
"AAAA": [
"2606:2800:220:1:248:1893:25c8:1946"
],
"MX": [
[
0,
"."
]
]
},
"doesnotexist.tld": {
"rcode": "NXDOMAIN"
}
}
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When parsing the padding size specification of a `J` format, e.g. `%.4J`,
the internally called `atoi()` function might read beyond the end of the
initialized memory within the format buffer, leading to non-deterministic
results.
Avoid overreading the initialized memory by parsing the padding length
manually digit-by-digit.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
syntax: introduce optional chaining operators
|
|
Introduce new operators `?.`, `?.[…]` and `?.(…)` to simplify looking up
deeply nested property chain in a secure manner.
The `?.` operator behaves like the `.` property access operator but yields
`null` if the left hand side is `null` or not an object.
Like `?.`, the `?.[…]` operator behaves like the `[…]` computed property
access but yields `null` if the left hand side is `null` or neither an
object or array.
Finally the `?.(…)` operator behaves like the function call operator `(…)`
but yields `null` if the left hand side is `null` or not a callable
function.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Reset all callframes when dealing with an unhandled exception to avoid
resuming the code which raised the exception when restarting the VM
later, e.g. through uc_vm_call() or uc_vm_invoke().
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
If execution in an existing VM that threw an exception was resumed
through uc_vm_call() or uc_vm_invoke(), the exception was never cleared,
causing all subsequent calls to return with an exception status as well.
Ensure that any preexisting exception information is discarded before
executing the requested function in order to start from a clean state.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
lib: introduce Linux 802.11 netlink binding
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When setting an array index which is beyond the end of the last currently
preallocated chunk and not evenly divisible by the chunk size, the array
entries list was not properly reallocated, resulting in invalid memory
writes.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|
|
When compiling certain expressions as first statement of an ucode
program, e.g. a while loop in raw mode, a jump instruction to offset
zero is emitted which was incorrectly treated as placeholder by the
compiler.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
|