Skip to content

Instantly share code, notes, and snippets.

@maxnordlund
Last active January 24, 2026 12:37
Show Gist options
  • Select an option

  • Save maxnordlund/18a289c1dbcc6639e40af4819d39beda to your computer and use it in GitHub Desktop.

Select an option

Save maxnordlund/18a289c1dbcc6639e40af4819d39beda to your computer and use it in GitHub Desktop.
An Elixir script to fix/adjust source location in all Elixir beam files so that elixir_ls got to definition works. The sources must be present, e.g. asdf installtions works but brew does not.
defmodule AdjustBeams do
def main() do
IO.puts("Fixing source in beams")
for {name, beam_file, _loaded} <- :code.all_available(),
beam_file != ~c"",
List.starts_with?(name, ~c"Elixir.") do
lib = Path.expand("#{beam_file}/../../..")
beam = File.read!(beam_file)
{:ok, _module, chunks} = :beam_lib.all_chunks(beam)
chunks = Enum.map(chunks, &update_chunk(lib, &1))
update_beam_file(beam_file, beam, chunks)
end
IO.puts("Done")
end
defp update_chunk(lib, {~c"CInf", chunk}) do
{~c"CInf", update_chunk(lib, chunk, [:source])}
end
defp update_chunk(lib, {~c"Dbgi", chunk}) do
{~c"Dbgi", update_chunk(lib, chunk, [Access.elem(2), Access.elem(1), :file])}
end
defp update_chunk(_lib, {name, chunk}) do
{name, chunk}
end
defp update_chunk(lib, chunk, path) when is_list(path) do
term = :erlang.binary_to_term(chunk)
case to_string(get_in(term, path)) do
"/home/runner/work/elixir/elixir/lib/" <> relative_path ->
source_file = Path.join(lib, relative_path)
:erlang.term_to_binary(put_in(term, path, source_file))
_ ->
chunk
end
end
defp update_beam_file(beam_file, beam, chunks) do
case :beam_lib.build_module(chunks) do
{:ok, ^beam} ->
IO.write(".")
{:ok, beam} ->
File.write!(beam_file, beam)
IO.write("*")
end
end
end
AdjustBeams.main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment