aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/src
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/src')
-rw-r--r--lib/kernel/src/hipe_unified_loader.erl47
-rw-r--r--lib/kernel/src/inet.erl105
-rw-r--r--lib/kernel/src/inet_int.hrl1
3 files changed, 125 insertions, 28 deletions
diff --git a/lib/kernel/src/hipe_unified_loader.erl b/lib/kernel/src/hipe_unified_loader.erl
index e676ca997d..0a0e6003ee 100644
--- a/lib/kernel/src/hipe_unified_loader.erl
+++ b/lib/kernel/src/hipe_unified_loader.erl
@@ -85,7 +85,7 @@ chunk_name(Architecture) ->
%%========================================================================
-spec load_native_code(Mod, binary()) -> 'no_native' | {'module', Mod}
- when is_subtype(Mod, atom()).
+ when Mod :: atom().
%% @doc
%% Loads the native code of a module Mod.
%% Returns {module,Mod} on success (for compatibility with
@@ -148,8 +148,8 @@ version_check(Version, Mod) when is_atom(Mod) ->
%%========================================================================
--spec load_module(Mod, binary(), _) -> 'bad_crc' | {'module',Mod}
- when is_subtype(Mod,atom()).
+-spec load_module(Mod, binary(), _) -> 'bad_crc' | {'module', Mod}
+ when Mod :: atom().
load_module(Mod, Bin, Beam) ->
erlang:system_flag(multi_scheduling, block),
try
@@ -169,8 +169,8 @@ load_module(Mod, Bin, Beam, OldReferencesToPatch) ->
%%========================================================================
--spec load(Mod, binary()) -> 'bad_crc' | {'module',Mod}
- when is_subtype(Mod,atom()).
+-spec load(Mod, binary()) -> 'bad_crc' | {'module', Mod} when Mod :: atom().
+
load(Mod, Bin) ->
erlang:system_flag(multi_scheduling, block),
try
@@ -204,15 +204,17 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch) ->
bad_crc;
true ->
%% Create data segment
- {ConstAddr,ConstMap2} = create_data_segment(ConstAlign, ConstSize, ConstMap),
+ {ConstAddr,ConstMap2} =
+ create_data_segment(ConstAlign, ConstSize, ConstMap),
%% Find callees for which we may need trampolines.
CalleeMFAs = find_callee_mfas(Refs),
%% Write the code to memory.
- {CodeAddress,Trampolines} = enter_code(CodeSize, CodeBinary, CalleeMFAs, Mod, Beam),
+ {CodeAddress,Trampolines} =
+ enter_code(CodeSize, CodeBinary, CalleeMFAs, Mod, Beam),
%% Construct CalleeMFA-to-trampoline mapping.
TrampolineMap = mk_trampoline_map(CalleeMFAs, Trampolines),
%% Patch references to code labels in data seg.
- patch_consts(LabelMap, ConstAddr, CodeAddress),
+ ok = patch_consts(LabelMap, ConstAddr, CodeAddress),
%% Find out which functions are being loaded (and where).
%% Note: Addresses are sorted descending.
{MFAs,Addresses} = exports(ExportMap, CodeAddress),
@@ -221,7 +223,7 @@ load_common(Mod, Bin, Beam, OldReferencesToPatch) ->
ok = remove_refs_from(MFAs),
%% Patch all dynamic references in the code.
%% Function calls, Atoms, Constants, System calls
- patch(Refs, CodeAddress, ConstMap2, Addresses, TrampolineMap),
+ ok = patch(Refs, CodeAddress, ConstMap2, Addresses, TrampolineMap),
%% Tell the system where the loaded funs are.
%% (patches the BEAM code to redirect to native.)
case Beam of
@@ -322,7 +324,7 @@ trampoline_map_get(MFA, Map) -> gb_trees:get(MFA, Map).
trampoline_map_lookup(_, []) -> []; % archs not using trampolines
trampoline_map_lookup(Primop, Map) ->
case gb_trees:lookup(Primop, Map) of
- {value,X} -> X;
+ {value, X} -> X;
_ -> []
end.
@@ -369,7 +371,7 @@ offsets_to_addresses(Os, Base) ->
find_closure_patches([{Type,Refs} | Rest]) ->
case ?EXT2PATCH_TYPE(Type) of
load_address ->
- find_closure_refs(Refs,Rest);
+ find_closure_refs(Refs, Rest);
_ ->
find_closure_patches(Rest)
end;
@@ -404,16 +406,17 @@ export_funs([FunDef | Addresses]) ->
hipe_bifs:set_native_address(MFA, Address, IsClosure),
export_funs(Addresses);
export_funs([]) ->
- true.
+ ok.
export_funs(Mod, Beam, Addresses, ClosuresToPatch) ->
- Fs = [{F,A,Address} || #fundef{address=Address, mfa={_M,F,A}} <- Addresses],
- code:make_stub_module(Mod, Beam, {Fs,ClosuresToPatch}).
+ Fs = [{F,A,Address} || #fundef{address=Address, mfa={_M,F,A}} <- Addresses],
+ Mod = code:make_stub_module(Mod, Beam, {Fs,ClosuresToPatch}),
+ ok.
%%========================================================================
%% Patching
%% @spec patch(refs(), BaseAddress::integer(), ConstAndZone::term(),
-%% Addresses::term(), TrampolineMap::term()) -> term()
+%% Addresses::term(), TrampolineMap::term()) -> 'ok'.
%% @type refs()=[{RefType::integer(), Reflist::reflist()} | refs()]
%%
%% @type reflist()= [{Data::term(), Offsets::offests()}|reflist()]
@@ -426,7 +429,7 @@ export_funs(Mod, Beam, Addresses, ClosuresToPatch) ->
%%
patch([{Type,SortedRefs}|Rest], CodeAddress, ConstMap2, Addresses, TrampolineMap) ->
- ?debug_msg("Patching ~w at [~w+offset] with ~w\n",
+ ?debug_msg("Patching ~w at [~w+offset] with ~w\n",
[Type,CodeAddress,SortedRefs]),
case ?EXT2PATCH_TYPE(Type) of
call_local ->
@@ -437,7 +440,7 @@ patch([{Type,SortedRefs}|Rest], CodeAddress, ConstMap2, Addresses, TrampolineMap
patch_all(Other, SortedRefs, CodeAddress, {ConstMap2,CodeAddress}, Addresses)
end,
patch(Rest, CodeAddress, ConstMap2, Addresses, TrampolineMap);
-patch([], _, _, _, _) -> true.
+patch([], _, _, _, _) -> ok.
%%----------------------------------------------------------------
%% Handle a 'call_local' or 'call_remote' patch.
@@ -459,14 +462,14 @@ patch_call([{DestMFA,Offsets}|SortedRefs], BaseAddress, Addresses, RemoteOrLocal
end,
patch_call(SortedRefs, BaseAddress, Addresses, RemoteOrLocal, TrampolineMap);
patch_call([], _, _, _, _) ->
- true.
+ ok.
patch_bif_call_list([Offset|Offsets], BaseAddress, BifAddress, Trampoline) ->
CallAddress = BaseAddress+Offset,
?ASSERT(assert_local_patch(CallAddress)),
patch_call_insn(CallAddress, BifAddress, Trampoline),
patch_bif_call_list(Offsets, BaseAddress, BifAddress, Trampoline);
-patch_bif_call_list([], _, _, _) -> [].
+patch_bif_call_list([], _, _, _) -> ok.
patch_mfa_call_list([Offset|Offsets], BaseAddress, DestMFA, DestAddress, Addresses, RemoteOrLocal, Trampoline) ->
CallAddress = BaseAddress+Offset,
@@ -474,7 +477,7 @@ patch_mfa_call_list([Offset|Offsets], BaseAddress, DestMFA, DestAddress, Address
?ASSERT(assert_local_patch(CallAddress)),
patch_call_insn(CallAddress, DestAddress, Trampoline),
patch_mfa_call_list(Offsets, BaseAddress, DestMFA, DestAddress, Addresses, RemoteOrLocal, Trampoline);
-patch_mfa_call_list([], _, _, _, _, _, _) -> [].
+patch_mfa_call_list([], _, _, _, _, _, _) -> ok.
patch_call_insn(CallAddress, DestAddress, Trampoline) ->
%% This assertion is false when we're called from redirect/2.
@@ -487,7 +490,7 @@ patch_call_insn(CallAddress, DestAddress, Trampoline) ->
patch_all(Type, [{Dest,Offsets}|Rest], BaseAddress, ConstAndZone, Addresses)->
patch_all_offsets(Type, Dest, Offsets, BaseAddress, ConstAndZone, Addresses),
patch_all(Type, Rest, BaseAddress, ConstAndZone, Addresses);
-patch_all(_, [], _, _, _) -> true.
+patch_all(_, [], _, _, _) -> ok.
patch_all_offsets(Type, Data, [Offset|Offsets], BaseAddress,
ConstAndZone, Addresses) ->
@@ -497,7 +500,7 @@ patch_all_offsets(Type, Data, [Offset|Offsets], BaseAddress,
patch_offset(Type, Data, Address, ConstAndZone, Addresses),
?debug_msg("Patching done\n",[]),
patch_all_offsets(Type, Data, Offsets, BaseAddress, ConstAndZone, Addresses);
-patch_all_offsets(_, _, [], _, _, _) -> true.
+patch_all_offsets(_, _, [], _, _, _) -> ok.
%%----------------------------------------------------------------
%% Handle any patch type except 'call_local' or 'call_remote'.
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index 5749027acd..27f085c3aa 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -200,7 +200,14 @@ send(Socket, Packet) ->
Options :: [socket_setopt()].
setopts(Socket, Opts) ->
- prim_inet:setopts(Socket, Opts).
+ SocketOpts =
+ [case Opt of
+ {netns,NS} ->
+ {netns,filename2binary(NS)};
+ _ ->
+ Opt
+ end || Opt <- Opts],
+ prim_inet:setopts(Socket, SocketOpts).
-spec getopts(Socket, Options) ->
{'ok', OptionValues} | {'error', posix()} when
@@ -209,7 +216,18 @@ setopts(Socket, Opts) ->
OptionValues :: [socket_setopt()].
getopts(Socket, Opts) ->
- prim_inet:getopts(Socket, Opts).
+ case prim_inet:getopts(Socket, Opts) of
+ {ok,OptionValues} ->
+ {ok,
+ [case OptionValue of
+ {netns,Bin} ->
+ {netns,binary2filename(Bin)};
+ _ ->
+ OptionValue
+ end || OptionValue <- OptionValues]};
+ Other ->
+ Other
+ end.
-spec getifaddrs(Socket :: socket()) ->
{'ok', [string()]} | {'error', posix()}.
@@ -641,6 +659,14 @@ con_opt([Opt | Opts], R, As) ->
{tcp_module,_} -> con_opt(Opts, R, As);
inet -> con_opt(Opts, R, As);
inet6 -> con_opt(Opts, R, As);
+ {netns,NS} ->
+ BinNS = filename2binary(NS),
+ case prim_inet:is_sockopt_val(netns, BinNS) of
+ true ->
+ con_opt(Opts, R#connect_opts { fd = [{netns,BinNS}] }, As);
+ false ->
+ {error, badarg}
+ end;
{Name,Val} when is_atom(Name) -> con_add(Name, Val, R, Opts, As);
_ -> {error, badarg}
end;
@@ -699,6 +725,14 @@ list_opt([Opt | Opts], R, As) ->
{tcp_module,_} -> list_opt(Opts, R, As);
inet -> list_opt(Opts, R, As);
inet6 -> list_opt(Opts, R, As);
+ {netns,NS} ->
+ BinNS = filename2binary(NS),
+ case prim_inet:is_sockopt_val(netns, BinNS) of
+ true ->
+ list_opt(Opts, R#listen_opts { fd = [{netns,BinNS}] }, As);
+ false ->
+ {error, badarg}
+ end;
{Name,Val} when is_atom(Name) -> list_add(Name, Val, R, Opts, As);
_ -> {error, badarg}
end;
@@ -745,6 +779,14 @@ udp_opt([Opt | Opts], R, As) ->
{udp_module,_} -> udp_opt(Opts, R, As);
inet -> udp_opt(Opts, R, As);
inet6 -> udp_opt(Opts, R, As);
+ {netns,NS} ->
+ BinNS = filename2binary(NS),
+ case prim_inet:is_sockopt_val(netns, BinNS) of
+ true ->
+ list_opt(Opts, R#udp_opts { fd = [{netns,BinNS}] }, As);
+ false ->
+ {error, badarg}
+ end;
{Name,Val} when is_atom(Name) -> udp_add(Name, Val, R, Opts, As);
_ -> {error, badarg}
end;
@@ -814,6 +856,17 @@ sctp_opt([Opt|Opts], Mod, R, As) ->
{sctp_module,_} -> sctp_opt (Opts, Mod, R, As); % Done with
inet -> sctp_opt (Opts, Mod, R, As); % Done with
inet6 -> sctp_opt (Opts, Mod, R, As); % Done with
+ {netns,NS} ->
+ BinNS = filename2binary(NS),
+ case prim_inet:is_sockopt_val(netns, BinNS) of
+ true ->
+ sctp_opt(
+ Opts, Mod,
+ R#sctp_opts { fd = [{netns,BinNS}] },
+ As);
+ false ->
+ {error, badarg}
+ end;
{Name,Val} -> sctp_opt (Opts, Mod, R, As, Name, Val);
_ -> {error,badarg}
end;
@@ -858,6 +911,39 @@ add_opt(Name, Val, Opts, As) ->
end.
+%% Passthrough all unknown - catch type errors later
+filename2binary(List) when is_list(List) ->
+ OutEncoding = file:native_name_encoding(),
+ try unicode:characters_to_binary(List, unicode, OutEncoding) of
+ Bin when is_binary(Bin) ->
+ Bin;
+ _ ->
+ List
+ catch
+ error:badarg ->
+ List
+ end;
+filename2binary(Bin) ->
+ Bin.
+
+binary2filename(Bin) ->
+ InEncoding = file:native_name_encoding(),
+ case unicode:characters_to_list(Bin, InEncoding) of
+ Filename when is_list(Filename) ->
+ Filename;
+ _ ->
+ %% For getopt/setopt of netns this should only happen if
+ %% a binary with wrong encoding was used when setting the
+ %% option, hence the user shall eat his/her own medicine.
+ %%
+ %% I.e passthrough here too for now.
+ %% Future usecases will most probably not want this,
+ %% rather Unicode error or warning
+ %% depending on emulator flag instead.
+ Bin
+ end.
+
+
translate_ip(any, inet) -> {0,0,0,0};
translate_ip(loopback, inet) -> {127,0,0,1};
translate_ip(any, inet6) -> {0,0,0,0,0,0,0,0};
@@ -1070,7 +1156,7 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
Result -> Result
end.
--spec open(Fd :: integer(),
+-spec open(Fd_or_OpenOpts :: integer() | list(),
Addr :: ip_address(),
Port :: port_number(),
Opts :: [socket_setopt()],
@@ -1080,8 +1166,14 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
Module :: atom()) ->
{'ok', socket()} | {'error', posix()}.
-open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 ->
- case prim_inet:open(Protocol, Family, Type) of
+open(FdO, Addr, Port, Opts, Protocol, Family, Type, Module)
+ when is_integer(FdO), FdO < 0;
+ is_list(FdO) ->
+ OpenOpts =
+ if is_list(FdO) -> FdO;
+ true -> []
+ end,
+ case prim_inet:open(Protocol, Family, Type, OpenOpts) of
{ok,S} ->
case prim_inet:setopts(S, Opts) of
ok ->
@@ -1104,7 +1196,8 @@ open(Fd, Addr, Port, Opts, Protocol, Family, Type, Module) when Fd < 0 ->
Error ->
Error
end;
-open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module) ->
+open(Fd, _Addr, _Port, Opts, Protocol, Family, Type, Module)
+ when is_integer(Fd) ->
fdopen(Fd, Opts, Protocol, Family, Type, Module).
bindx(S, [Addr], Port0) ->
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 67a99913a1..18a4a61b2f 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -143,6 +143,7 @@
-define(INET_LOPT_TCP_SEND_TIMEOUT_CLOSE, 35).
-define(INET_LOPT_MSGQ_HIWTRMRK, 36).
-define(INET_LOPT_MSGQ_LOWTRMRK, 37).
+-define(INET_LOPT_NETNS, 38).
% Specific SCTP options: separate range:
-define(SCTP_OPT_RTOINFO, 100).
-define(SCTP_OPT_ASSOCINFO, 101).